Trie

  • Trie基本介绍

1.是一种多叉树
2.专门处理字符串
3.查询每个条目的时间复杂度,和字典映射中一共多少条目无关
4.其时间复杂度为O(w),w为所查询单词的长度
5.大多数单词的长度小于10(优势)

  • Trie性质

1、根节点不包含字符,除根节点外每一个节点都只包含一个字符。
2、从根节点到某一节点,路径上经过的字符连接起来,为该节点对应的字符串。
3、每个节点的所有子节点包含的字符都不相同。
应用的场景就是查询字符串,字符串的前缀,词频统计等等。
优点:查询的效率非常高,缺点是利用空间换取时间。
实现原理:利用Trie树节点组织成一棵树,每个节点包含两个值,一个代表该字符的添加次数,另一个代表以该字符结尾的字符串个数。路径上用于存储字符。存储字符可以利用数组指针也可以利用哈希结构实现。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • Trie的实现
package org.yanan.Trie;

import java.util.TreeMap;

public class Trie {
	//1.定义内部类
	private class Node{
		boolean isWord;//当前为止,是否组成一个单词
		TreeMap<Character,Node> nexts;//当前之后的字母以及其映射后的结点
		public Node(boolean isWord){
			this.isWord=isWord;
			nexts=new TreeMap<>();
		}
		public Node(){
			this(false);
		}
	}
	//2.定义成员变量和构造函数
	private Node root;
	private int size;
	public Trie(){
		root=new Node();
		size=0;
	}
	//3.向Trie中添加一个新的单词
	public void add(String word){
		Node cur=root;//cur从根开始
		for(int i=0;i<word.length();i++){
			char c=word.charAt(i);
			if(cur.nexts.get(c)==null){//若树中无该字母,cur的映射map中通过c找到的结点为空
				cur.nexts.put(c, new Node());//将该字母加入树中
			}
			cur=cur.nexts.get(c);//更新cur的值
		}
		//标记此时已经是一个单词了,但为了避免相同单词出现,判断一下
		if(!cur.isWord){//在它不是一个单词时,将其改成一个单词
			cur.isWord=true;
			size++;
		}
	}
	//4.查询单词是否在Trie树中
	public boolean contains(String word){
		Node cur=root;
		for(int i=0;i<word.length();i++){
			char c=word.charAt(i);
			if(cur.nexts.get(c)==null){
				return false;
			}
			cur=cur.nexts.get(c);
		}
		return cur.isWord;//如果不是一个单词,只有一个单词的前一部分
	}
	//5.查询是否在Trie中有单词以prefix为前缀
	public boolean isPrefix(String prefix){
		Node cur=root;
		for(int i=0;i<prefix.length();i++){
			char c=prefix.charAt(i);
			if(cur.nexts.get(c)==null){
				return false;
			}
			cur=cur.nexts.get(c);
		}
		return true;//前缀
	}
}
==============================Main================================
package org.yanan.Trie;

public class Main {
	public static void main(String[] args) {
		Trie trie=new Trie();
		trie.add("dog");
		trie.add("door");
		trie.add("does");
		trie.add("cat");
		trie.add("capacity");
		trie.add("can");
		trie.add("panada");
		System.out.println(trie.contains("do"));
		System.out.println(trie.isPrefix("ca"));
	}
}
=========================比较速度:Main1============================
package org.yanan.Trie;

import java.util.ArrayList;

import org.openlab.集合与映射.BSTSet;

public class Main2 {
	public static void main(String[] args) {
		ArrayList<String> words=new ArrayList<>();
		FileOperation.readFile("pride-and-prejudice.txt", words);
		double time1=testTime(true,words);
		double time2=testTime(false,words);
		System.out.println("Trie:"+time1);
		System.out.println("BSTSet:"+time2);
	}

	private static double testTime(boolean b, ArrayList<String> words) {
		long startTime=System.currentTimeMillis();
		if(b){
			Trie trie=new Trie();
			for(String word:words){
				trie.add(word);
			}
			for(String word:words){
				trie.contains(word);
			}
		}else{
			BSTSet<String> set=new BSTSet<>();
			for(String word:words){
				set.add(word);
			}
			for(String word:words){
				set.contains(word);
			}
		}
		long endTime=System.currentTimeMillis();
		return endTime-startTime;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值