字典树(Trie树)

字典树又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种。java

典型应用:用于统计,排序和保存大量的字符串(但不只限于字符串),因此常常被搜索引擎系统用于文本词频统计。node

优势:利用字符串的公共前缀来减小查询时间,最大限度地减小无谓的字符串比较,查询效率比哈希树高。ios

实现方法
搜索字典项目的方法为:
(1) 从根结点开始一次搜索;
(2) 取得要查找关键词的第一个字母,并根据该字母选择对应的子树并转到该子树继续进行检索;
(3) 在相应的子树上,取得要查找关键词的第二个字母,并进一步选择对应的子树进行检索。
(4) 迭代过程……
(5) 在某个结点处,关键词的全部字母已被取出,则读取附在该结点上的信息,即完成查找。
其余操做相似处理c++

插入字符串图解(例如”csdn“)
一、一开始为空树,指针节点为头节点,从头节点开始查找,是否有”c“这个节点。(头节点不储存数据)
空树
二、不存在”c“这个节点,则在指针下添加子节点”c“。
在这里插入图片描述
三、此时将指针节点赋值为“c”,则在”c“中寻找下一个要添加的字符”s“,不存在,重复2步骤添加,如果存在,则直接将指针节点赋值为此节点便可。如此反复,直到全部的字符添加完毕。
在这里插入图片描述
四、最后将最后添加的节点的末节点值增长,表示以此为末节点的数量为1。
在这里插入图片描述
五、字符串”csdn“就添加完成了。同理,查询、删除等操做也是如此,从头节点开始,一个个搜寻。web

c++代码数组

#include<iostream>
#include<cstdio>
using namespace std;
typedef struct Node node;
struct Node{
	int id;//标记是否为尾节点,同时统计数量 
	node *next[26];
	Node(){
		for(int i=0;i<26;i++){
			next[i]=NULL;
		}
		id=0;
	}
}*root=new Node();
int W;
void insert(string str){//建表插入 
	int len=str.length();
	int index=0;
	node* tail=root;
	for(int i=0;i<len;i++){
		index=str[i]-'A';
		if(tail->next[index]==NULL){
			tail->next[index]=new Node(); 
		}
		tail=tail->next[index];
	}
	tail->id++;
}
bool contain(string str){
	node *tail=root;
	for(int i=0;i<str.length();i++){
		if(tail->next[str[i]-'A']!=NULL){
			tail=tail->next[str[i]-'A'];
		}else{
			return false;
		}
	}
	return tail->id>0;
}
int main(){
	string te;
	cin>>W;
	for(int j=0;j<W;j++){ 
		cin>>te;
		insert(te);
	}
	for(int k=0;k<10;k++){
		string x;
		cin>>x;
		cout<<"HAVE "<<x<<" ? :";
		if(contain(x)){        
			cout<<"Yes"; 
		}else{
			cout<<"No"; 
		}
		cout<<endl;
	}
}

java代码svg

import java.util.ArrayList;

public class Trie{//字典树类
    Node head=new Node();
    class Node{//节点
        char data;//节点数据
        int Endnum=0;//以此为末节点的数量(表明有几个此单词)
        ArrayList<Node> childList=new ArrayList<>();//子节点,直接用数组,增长、删除、查找等效率会更高
        Node(){}
        Node(char ch){
            this.data=ch;
        }
        Node addchild(char data){
            Node child=new Node(data);
            childList.add(child);
            return child;
        }
        void delete(){
            this.Endnum--;//减少末节点标记
        }
        Node isHave(char data){
            for (Node node:childList){
                if (node.data==data){
                    return node;
                }
            }
            return null;
        }
    }
    public void add(String str){
        char[] chars=str.toCharArray();
        Node node=head,temp=null;
        for (int i=0;i<chars.length;i++){
            if ((temp=node.isHave(chars[i]))!=null){//寻找是否有此节点
                node=temp;
            }else{
                node=node.addchild(chars[i]);//新建节点,同时赋值
            }
        }
        node.Endnum++;//将最后一个标记为终节点,说明有此字符串
    }
    public void delete(String str){
        char[] chars=str.toCharArray();
        Node node=head,temp=null;
        for (int i=0;i<chars.length;i++){
            temp=node.isHave(chars[i]);
            if (temp!=null){
                node=temp;
            }else{
                System.out.println("无此字符串");
                return;
            }
        }
        node.delete();//取消最后一个标记
    }
    public int isHave(String str){//返回0或-1表示无此字母
        char[] chars=str.toCharArray();
        Node node=head,temp=null;
        for (int i=0;i<chars.length;i++){
            temp=node.isHave(chars[i]);
            if (temp==null){
                return -1;
            }else{
                node=temp;
            }
        }
        return node.Endnum;
    }
}

操做演示this

public class Main {
    public static void main(String[] args) {
        Trie trie=new Trie();
        trie.add("abc");//添加
        trie.add("abc");
        trie.add("abc");
        trie.delete("abc");//删除
        System.out.println(trie.isHave("abc"));//查找
    }
}

运行结果
在这里插入图片描述搜索引擎

参考资料:字典树_百度百科spa