`

Trie

 
阅读更多

Trie.

import java.util.*;
public class Trie {

	private static final int R = 26;
	
	private static class TrieNode {
		boolean isLeaf; //是否为单词的结尾
		int count; //以此节点为prefix的字符串的个数, 此属性不是必须的
		TrieNode[] childs = new TrieNode[R];
	}
	
	private TrieNode root = new TrieNode();
	private int size;
	
	public int size() {
		return size;
	}
	
	//if the word does not exist in the dict, insert it, mark the leaf node, increment dict size
	public void insert(String word) {
		if(word==null || word.isEmpty() || contains(word)) return;
		TrieNode node = root;
		for(int i=0; i<word.length(); i++) {
			char c = word.charAt(i);
			int j = c - 'a';
			if(node.childs[j] == null) {
				node.childs[j] = new TrieNode();
			}
			node = node.childs[j];
			node.count++;
		}
		
		if(!node.isLeaf) {
			node.isLeaf = true;
			size++;
		}
	}
	
	public boolean contains(String word) {
		TrieNode node = root;
		for(int i=0; i<word.length(); i++) {
			char c = word.charAt(i);
			int j = c - 'a';
			node = node.childs[j];
			if(node == null) return false;
		}
		return node.isLeaf;
	}
	
	// 1. Key may not be there in trie. Delete operation should not modify trie.
	// 2. Key present as unique key (no part of key contains another key (prefix),
	//    nor the key itself is prefix of another key in trie). Delete all the nodes.
	// 3. Key is prefix key of another long key in trie. Unmark the leaf node.
	// 4. Key present in trie, having at least one other key as prefix key. Delete
	//    nodes from end of key until first leaf node of longest prefix key.
	public boolean delete(String word) {
		if(word==null || word.isEmpty()) return false;
		return delete(root, word, 0);
	}
	
	private boolean delete(TrieNode node, String word, int d) {
		if(node == null) return false;
		if(d == word.length()) {
			if(node.isLeaf) {
				node.isLeaf = false;
				size--;
				return true;
			}
			return false;
		} 
		int k = word.charAt(d) - 'a';
		TrieNode next = node.childs[k];
        boolean ok = delete(next, word, d+1);
        if(ok && --next.count == 0) {
    		node.childs[k] = null;
        }
        return ok;
	}
	
	// yet another method of delete
	public void remove(String word) {
		if(word == null || word.isEmpty()) return;
		remove(root, word, 0);
	}
	
	private TrieNode remove(TrieNode node, String word, int d) {
		if(node == null) return null;
		if(d == word.length()) {
			if(node.isLeaf) {
				node.isLeaf = false;
				size--;
			}
		} else {
			int k = word.charAt(d) - 'a';
			node.childs[k] = remove(node.childs[k], word, d+1);
		}
		for (int i = 0; i < R; i++)
            if (node.childs[i] != null)
                return node;
		return null;
	}
	
	public List<String> words() {
		return wordsWithPrefix("");
	}
	
	public List<String> wordsWithPrefix(String prefix) {
		List<String> list = new ArrayList<>();
		TrieNode node = root;
		for(int i=0; i<prefix.length(); i++) {
			node = node.childs[prefix.charAt(i) - 'a'];
		}
		StringBuilder sb = new StringBuilder(prefix);
		collect(node, sb, list);
		return list;
	}
	
	private void collect(TrieNode node, StringBuilder prefix, List<String> list) {
		if(node == null) return;
		if(node.isLeaf) list.add(prefix.toString());
		for(int i=0; i<R; i++) {
			prefix.append((char)(i+'a'));
			collect(node.childs[i], prefix, list);
			prefix.deleteCharAt(prefix.length()-1);
		}
	}
	
	public String longestPrefixOf(String query) {
        int length = longestPrefixOf(root, query, 0, 0);
        return query.substring(0, length);
    }

    private int longestPrefixOf(TrieNode x, String query, int d, int length) {
        if (x == null) return length;
        if (x.isLeaf) length = d;
        if (d == query.length()) return length;
        char c = query.charAt(d);
        return longestPrefixOf(x.childs[c-'a'], query, d+1, length);
    }
}

 

Test case:

public static void main(String[] args) {
	String[] words = {"the", "a", "there", "answer", "any", "by", "bye", "their", "grass"};
	Trie trie = new Trie();
	for (String word : words) {
		trie.insert(word);
	}
	System.out.println(trie.longestPrefixOf("an"));
	System.out.println(trie.wordsWithPrefix("an"));
	System.out.println(trie.size());
	System.out.println(trie.contains("the"));
	System.out.println(trie.contains("they"));
	System.out.println(trie.contains("by"));
	System.out.println(trie.contains("byn"));
	System.out.println(trie.contains("any"));
	trie.remove("any");
	System.out.println("delete ans:" + trie.delete("ans"));
	System.out.println(trie.contains("any"));
	System.out.println(trie.contains("answer"));
	trie.remove("answer");
	System.out.println(trie.contains("answer"));
	trie.remove("by");
	System.out.println(trie.contains("by"));
	System.out.println("delete by:" + trie.delete("by"));
	System.out.println(trie.contains("bye"));
	System.out.println(trie.size());
}

 

References:

http://algs4.cs.princeton.edu/52trie/TrieST.java.html

http://www.geeksforgeeks.org/trie-delete/

分享到:
评论

相关推荐

    trie-0.1.1.tar

    Trie数据结构详解与应用 Trie,又称为前缀树或字典树,是一种用于存储字符串的树形数据结构。它的主要特点是通过关联字符来构建树的节点,从而实现快速的字符串查找、插入和删除操作。Trie在信息技术、搜索引擎优化...

    Go-trie-单词查找树实现Go实现

    在这个背景下,了解并掌握如何在Go中实现Trie(单词查找树)这种数据结构对于提升代码质量具有重要意义。 Trie,又称为前缀树或字典树,是一种用于存储动态集合或关联数组的树形数据结构。它的主要特点是通过键的...

    trie数组的算法实现

    - libdatrie 提供了 C 语言接口,包括 trie_load() 函数加载词典,trie_insert() 插入新词,trie_search() 查找单词,以及 trie_delete() 删除单词等方法。 - 库还支持 Trie 的序列化和反序列化,便于在内存和磁盘...

    Trie 树实现的源码

    ### Trie树实现详解 #### 一、Trie树简介 Trie树,也称为前缀树或字典树,是一种用于存储字符串数据结构。它利用字符串间的公共前缀来减少所需的存储空间,使得查找字符串更加高效。Trie树在很多应用中都有广泛的...

    从trie树谈到后缀树

    【Trie树】 Trie树,又称为字典树,是一种特殊的树形数据结构,主要用于高效地存储和检索字符串。它的设计目的是通过利用字符串的公共前缀来减少字符串比较的次数,从而提高查询效率。Trie树的核心特点是: 1. 根...

    DoubleArrayTrie(双数组Trie树)

    **DoubleArrayTrie(双数组Trie树)详解** DoubleArrayTrie(简称DAT),是一种高效的数据结构,常用于字符串的查找和匹配,特别是在分词检索、数据挖掘以及搜索引擎等领域有着广泛的应用。它是由日本学者高津陵...

    Trie树入门,很容易上手

    "Trie树入门,很容易上手" Trie树是一种树形结构,用于保存大量的字符串。它的优点是:利用字符串的公共前缀来节约存储空间。相对来说,Trie树是一种比较简单的数据结构。理解起来比较简单,但是简单的东西也得付出...

    11 TrieTree.rar

    《严蔚敏数据结构与算法:TrieTree详解》 在计算机科学中,数据结构是组织、管理和存储数据的方式,而算法则是解决特定问题的精确步骤。数据结构的选择直接影响到程序的效率和可读性。在众多的数据结构中,TrieTree...

    Algorithm-trie.zip

    Trie,也被称为前缀树或字典树,是一种用于存储键值对的数据结构,尤其适用于字符串数据。在C语言中实现Trie,可以提供快速的字符串查找服务,尤其是在处理大量字符串且需要查找是否存在某个字符串或者字符串前缀时...

    实现trie树的C/C++模板

    ### 实现Trie树的C/C++模板 在计算机科学领域,Trie树(又称前缀树或字典树)是一种用于存储具有共同前缀的字符串的高效数据结构。它广泛应用于各种场景,如自动补全、拼写检查以及IP路由表等。本文将详细介绍如何...

    trie树的实现(C)

    trie.c中定义了trie树的操作函数; trie.h为相应的头文件; test.c用于测试相关的函数。 在trie.c中,关于查找定义了两个函数,一个是find(),一个是search(),二者的区别是,前者仅判断一个字符串是否在树中出现,...

    IT笔试面试--Trie树前缀树常考题目及解析

    ### IT笔试面试--Trie树(前缀树)常考题目及解析 #### 概述 Trie树,又称字典树或前缀树,是一种用于快速检索的多叉树结构,广泛应用于字符串处理领域。它能有效地利用字符串的公共前缀来减少存储空间,并在查询...

    双数组Trie优化算法及其应用研究

    ### 双数组Trie优化算法及其应用研究 #### 摘要 本文主要探讨了双数组Trie树(Double-Array Trie)算法的一种优化方法,并详细分析了其在实际应用中的表现,特别是在词典管理和自动分词领域。双数组Trie树作为一种...

    Trie树 linux32 SDK V3.0

    2、Trie树SDK中的API支持以下功能 1)插入节点 2)精确删除节点 3)正向模糊匹配 4)反向模糊匹配 5)精确查询节点 6)获取头(尾)节点 7)删除头(尾)节点 8)排序 9)支持多级树 10)支持强大的查询节点功能 ...

    KMP算法与trie搜索树实现

    KMP算法和Trie搜索树是两种在计算机科学中用于字符串处理的重要算法,它们在文本检索、模式匹配和数据结构优化等领域有着广泛的应用。 首先,我们来深入了解一下KMP算法。KMP(Knuth-Morris-Pratt)算法是一种高效...

    Trie树 结构描述 实现方法 用法

    Trie树,也被称为前缀树或字典树,是一种数据结构,主要用于高效地存储和检索字符串。在Trie树中,每个节点代表一个字符串的前缀,而从根节点到某个节点的路径上的边代表了这个节点所代表的字符串。这种结构特别适合...

    实现Trie_java_

    Trie,又称为字典树或前缀树,是一种用于存储关联数组的数据结构,它允许我们高效地进行字符串的查找、插入和删除操作。在Java中实现Trie数据结构,可以帮助我们快速处理大量字符串数据,例如在搜索引擎中进行关键词...

    用Trie树实现词频统计和单词查询

    一个简单的C语言程序:用Trie树实现词频统计和单词查询

Global site tag (gtag.js) - Google Analytics