字典樹

字典樹

1.1 基本數據結構

數據結構大都離不開數組鏈表。他們是計算機中最基本的數據機構,基本全部的數據機構均可以有這兩種數據機構來實現。java

而鏈表是一種特殊的樹,樹更是一種特殊的圖。node

極客時間 數學專欄的做者的一段話,一直以爲很受用:算法

其實計算機到了最後仍是搞數學,咱們要作的就是如何將問題應用到數學在到編程上去。編程

數學思想到編程的實現大都分爲三步走數組

  • 把問題轉化爲數學中的模型
  • 用數據結構與算法來刻畫數學模型
  • 落實編碼

1.2 字典樹

1.2.1 什麼是字典樹?數據結構

字典樹也能夠叫作前綴樹,其實就是將不少單詞組成的一種數據機構。一般都是樹形結構的全部叫作字典樹。ui

以下圖所示:this

跟節點一般都是空,不一樣的單詞組成一條條的通路,造成了一個樹狀結構。編碼

字典樹有兩種實現方式鏈表數組spa

由於字典樹的二維關係是很是稀疏很是動態的,因此採用鏈表來實現字典樹。

具體的代碼註釋以下:

static class TreeNode{

        /** * 節點的數據void */
        private char data;

        /** * 子節點 */
        private Map<Character,TreeNode>  sons = null;

        /** * 節點的解釋 */
        private String explanation = null;

        /** * 節點的前綴字符串 */
        private String prefix = null;


        public TreeNode(char data, String explanation, String prefix) {
            this.data = data;
            this.sons = new HashMap<>(16);
            this.explanation = explanation;
            this.prefix = prefix;
        }
    }
複製代碼

1.2.2 字典樹的操做

字典樹有兩種

由於字典樹的二維關係是很是稀疏很是動態的,

字典樹的操做有兩個

  • 構建字典樹(Dynamic)

    public static void buildPrefixTree(String word){
            if(StringUtils.isEmpty(word)) {
                return;
            }
    
            TreeNode findNode = headNode;
            String prefix = "";
            String explanation = null;
    
            for(int i=0;i<word.length();i++){
                char c = word.charAt(i);
                Map<Character, TreeNode> sons = findNode.sons;
                if(sons.containsKey(c)){
                    findNode = sons.get(c);
                }else{
                    if(i == word.length()-1){
                        explanation = prefix + c;
                    }
                    TreeNode sonNode = new TreeNode(c,explanation,prefix);
                    sons.put(c,sonNode);
                    findNode = sonNode;
                }
                prefix += c;
            }
        }
    複製代碼
  • 查詢字典

/** * 在PrefixTree中查找 單詞 * @param word * @return */
    public static TreeNode findWrod(String word){

        if(StringUtils.isEmpty(word)) {
            return null;
        }
        TreeNode findNode = headNode;

        for(int i=0;i<word.length();i++){
            char c = word.charAt(i);
            Map<Character, TreeNode> sons = findNode.sons;

            if( sons.size()!=0 && sons.containsKey(c)){
                findNode = sons.get(c);
            }else{
                return null;
            }
        }

        if(StringUtils.isEmpty(findNode.explanation)){
            return null;
        }

        return findNode;
    }
複製代碼
  • 遍歷字典樹中的全部單詞

    /** * 使用棧便利全部的單詞 */
        public static void dfsByStack(){
            Stack<TreeNode>  stack = new Stack<>();
            stack.push(headNode);
            while(stack.size()>0){
                TreeNode node = stack.pop();
                if(!StringUtils.isEmpty(node.explanation)){
                    System.out.println(node.explanation);
                }
                Map<Character, TreeNode> sons = node.sons;
                sons.forEach((sonKey,sonValue)->{
                    stack.push(sonValue);
                });
            }
        }
    複製代碼

字典樹的這三種操做其實均可以用遞歸來實現,可是最後一種的效率是明顯優於遞歸的,由於減小了大量的中間變量的建立,利用了棧模擬了遞歸調用。

相關文章
相關標籤/搜索