(314)字典树与三向字典树-java实现

引言

用java实现的单词树与三向单词树。

理论

参考:

单词查找树(Tries)

Trie—单词查找树

代码(java)

package org.hirudy.practice;

/**
 * @author: rudy
 * @date: 2016/08/15
 * 
 * 单词树,三向单词树
 *
 */
public class TriePractice {

    /**
     * 单词树类
     */
    public static class SimpleTrie{
        public static final int R = 256; // R向单词查找数的next数组大小
        private Node root = new Node();

        public class Node {
            boolean isContain = false; // 是否包含当前节点
            public Node[] next = new Node[R]; // R向数组
        }

        public boolean insert(String word){
            return insert(word, root, 0);
        }

        /**
         * 向单词树中插入单词
         * @param word
         * @param node
         * @param deepth
         * @return
         */
        protected boolean insert(String word, Node node, int deepth){
            if (word == null){
                return false;
            }

            if (deepth == word.length()){
                node.isContain = true;
                return true;
            }

            char tmp = word.charAt(deepth);
            if(node.next[tmp] == null){
                node.next[tmp] = new Node();
            }

            return insert(word, node.next[tmp], deepth + 1);
        }

        /**
         * 判断单词是否存在于单词树中
         * @param word
         * @return
         */
        public boolean isExist(String word){
            int wordLength = word.length();
            Node tmpNode = this.root;
            int deepth;
            for (deepth=0; deepth < wordLength; deepth++){
                char tmpChar = word.charAt(deepth);
                if (tmpNode.next[tmpChar] == null){
                    break;
                }
                tmpNode = tmpNode.next[tmpChar];
            }

            if (deepth == wordLength && tmpNode.isContain){
                return true;
            }
            return false;
        }
    }

    /**
     * 三向单词树类
     */
    public static class TernaryTrie{
        private Node root; // 根节点

        public class Node {
            public boolean isContain = false; // 是否包含当前节点
            public char currentChar; //当前节点包含的字符
            public Node left,middle,right; // 三个方向的节点链接
        }

        public void insert(String word){
            if (word.length() <= 0){
                return;
            }
            this.root = insert(word, this.root, 0);
        }

        protected Node insert(String word, Node node, int deepth){
            char tmpChar = word.charAt(deepth);
            if (node == null){
                node = new Node();
                node.currentChar = tmpChar;
            }

            if (tmpChar < node.currentChar){
                node.left = insert(word, node.left,deepth);
            }else if (tmpChar > node.currentChar){
                node.right = insert(word, node.right,deepth);
            }else if(deepth < word.length()-1){
                node.middle = insert(word,node.middle, deepth+1);
            }else{
                node.isContain = true;
            }

            return node;
        }

        public boolean isExist(String word){
            int wordLength = word.length();
            int deepth = 0;
            Node tmpNode = root;
            boolean isLastNode = false;

            while (deepth < wordLength){
                if (tmpNode == null){
                    break;
                }
                char tmpChar = word.charAt(deepth);
                if (tmpChar == tmpNode.currentChar){
                    deepth ++;
                    if (deepth == wordLength){
                        isLastNode = tmpNode.isContain;
                    }
                    tmpNode = tmpNode.middle;
                }else if (tmpChar < tmpNode.currentChar){
                    tmpNode = tmpNode.left;
                }else if (tmpChar > tmpNode.currentChar){
                    tmpNode = tmpNode.right;
                }
            }

            if (deepth == wordLength && isLastNode){
                return true;
            }

            return false;
        }
    }

    public static void main(String[] args){
        // 简单的字典树验证
        System.out.println("simple trie check:");
        String[] wordList = new String[]{"aaa","bba","test","trie","test1","term","hello","hello_world"};
        SimpleTrie simpleTrie = new SimpleTrie();
        for (String word : wordList){
            simpleTrie.insert(word);
        }

        System.out.println(simpleTrie.isExist("trie"));
        System.out.println(simpleTrie.isExist("term"));
        System.out.println(simpleTrie.isExist("tes"));
        System.out.println(simpleTrie.isExist("hello"));
        System.out.println(simpleTrie.isExist("hello_"));

        // 三向字典树验证
        System.out.println("ternary trie check:");
        String[] wordList2 = new String[]{"aaa","b中a","test","tr文ie","test1","term","hello","hello_world"};
        TernaryTrie ternaryTrie = new TernaryTrie();
        for (String word : wordList2){
            ternaryTrie.insert(word);
        }

        System.out.println(ternaryTrie.isExist("trie"));
        System.out.println(ternaryTrie.isExist("term"));
        System.out.println(ternaryTrie.isExist("tr文ie"));
        System.out.println(ternaryTrie.isExist("hello"));
        System.out.println(ternaryTrie.isExist("hello_"));
    }
}

结果

图1.字典树的执行结果
package TrieTree

type TrieNode struct {
    data string
    nextNodes map[string]*TrieNode
    isLastNode bool
}

type WordTrie struct {
    Head map[string]*TrieNode
}

func (w *WordTrie) AddWord(word string) {
    if "" == word {
        return
    }
    wordList := []rune(word)
    wordLen := len(wordList)
    currentNodes := w.Head
    for i:=0; i< wordLen; i++ {
        str := string(wordList[i])
        if currentNodes[str] == nil {
            tempNode := TrieNode {
                data: str,
                nextNodes: map[string]*TrieNode{},
                isLastNode: false,
            }
            currentNodes[str] = &tempNode
        }
        if i == wordLen -1 {
            currentNodes[str].isLastNode = true
        }
        currentNodes = currentNodes[str].nextNodes
    }
}

func (w *WordTrie) SearchWord(text string) (word string, index int) {
    if "" == text {
        return
    }
    textList := []rune(text)
    textLen := len(textList)
    for i:=0;i< textLen;i++ {
        currentTrieNode := w.Head
        for j:=i; j<textLen; j++ {
            str := string(textList[j])
            if currentTrieNode[str] == nil {
                break
            }
            if currentTrieNode[str].isLastNode == true {
                return string(textList[i:j+1]), i
            }
            currentTrieNode = currentTrieNode[str].nextNodes
        }
    }
    return "", -1
}


// go版本
func main()  {
    trie := TrieTree.WordTrie{Head: map[string]*TrieTree.TrieNode{}}
    trie.AddWord("中国")
    trie.AddWord("日本")
    trie.AddWord("中人")

    println(trie.SearchWord("中日本人民"))
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,451评论 25 707
  • BWA Burrows-Wheeler Aligner作为一个十分出名的alignment软件,在各个生信领域的比...
    栽生物坑里的信息汪阅读 4,596评论 0 5
  • 一. Java基础部分.................................................
    wy_sure阅读 3,788评论 0 11
  • 今天突然冒出一个新的想法,想把自己在为公解惑平台实证的小游戏通过文字的方式记录下来,一方面是对自我成...
    文武娃娃阅读 1,716评论 11 9
  • 贫贱所难,不难在砥节,而难在用情;富贵所难,不难在推恩,而难在好礼。 蛾扑火,火焦蛾,莫谓祸生无本;果种花,花结果...
    HedyWang1阅读 141评论 0 0