算法--前缀树

前缀树上面的每一个节点,都可以有很多个子树,通往不同子树的路径上的字符串也不同。通常用于保存字符串,以及查询字符串,通过前缀相同来减少查询时间。

前缀树首先要有一个根节点。假设我需要存储三个字符串分别是"abc" "abd" "bcd"。

开始的时候根节点没有通向a的路径于是根节点创建出一条通向'a'的路径

到达下一个节点之后发现没有通向‘b’的路径于是再创建路径。后面是一样的

 最后就是一个这样的图。

每个节点中包含一个集合,集合中表示它可以通向的下一个节点,也就是路径。如果增加字符串的时候发现没有这条路径,就会创建出来。

节点中还可以包含其他信息。pass表示有多少个字符串以这条路径为前缀,end表示这条路径有多少个一样的字符串加入。

	public static class TrieNode{
		public int pass;//前缀为这条路的有多少个
		public int end;//加入了多少个这样的字符串
		public TrieNode[] nexts;//如果字符特别多的话,可以将数组改成HashMap<char,TrieNode>
		public TrieNode(){
			pass = 0;
			end = 0;
			//nexts[0] == null 那么就没有通向'a'的路
			//nexts[0] != null 存在通向'a'的路
			//nexts[25] == null 不存在通向'z' 的路
			nexts = new TrieNode[26];
		}
	}
	
	public static class Trie{
		private TrieNode root;
		public Trie() {
			this.root = new TrieNode();
		}
		
		public void insert(String word) {
			if(word == null) {
				return;
			}
			char[]  chs = word.toCharArray();
			TrieNode node = root;
			root.pass++;
			int index = 0;
			for(int i=0;i<chs.length;i++) {
				index = chs[i] - 'a';
				if(node.nexts[index] == null) {
					node.nexts[index] = new TrieNode();
				}
		
				node = node.nexts[index];
				node.pass++;
			}
			node.end++;
			
			
		}
		//查询一个字符串加入过几次
		public  int search(String word) {
			if(word == null) {
				return 0;
			}
			char[] chs = word.toCharArray();
			TrieNode node = root;
			int index = 0;
			for(int i=0;i<chs.length;i++) {
				index = chs[i] - 'a';
				if(node.nexts[index] == null) {
					return 0;
				}
				node = node.nexts[index];
			}
			return node.end;
		}
		
		//加入的字符串中有几个是以pre为前缀的
		public int preFixnumber(String pre) {
			if(pre == null) {
				return 0;
			}
			char[] chs = pre.toCharArray();
			TrieNode node = root;
			int index = 0;
			for(int i=0;i<chs.length;i++) {
				index = chs[i] - 'a';
				if(node.nexts[index] == null) {
					return 0;
				}
				node = node.nexts[index];
			}
			
			return node.pass;
		}
		
		public void delete(String word) {
			if (search(word) != 0) {// 确定树中存在这个节点才删除
				char[] chs = word.toCharArray();
				int index = 0;
				TrieNode node = root;
				node.pass--;
				for (int i = 0; i < chs.length; i++) {
					index = chs[i] - 'a';
					if (--node.nexts[index].pass == 0) {
						// 如果这个字符串只存在一次,删除之后这条路就不存在了,得置空
						node.nexts[index] = null;
						return;
					}
					node = node.nexts[index];

				}
				node.end--;

			}

		}
		
		
		
		
	}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值