成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

算法(第4版) Chapter 5.2 單詞查找樹(shù)

tigerZH / 1211人閱讀

摘要:謝路云單詞查找樹(shù)查找所需要的單詞的時(shí)間和鍵的長(zhǎng)度成正比查找未命中只需檢查若干個(gè)單詞單詞查找樹(shù)單詞查找樹(shù)基本性質(zhì)每個(gè)鏈接對(duì)應(yīng)一個(gè)字符每個(gè)結(jié)點(diǎn)可能有一個(gè)值有值,說(shuō)明存在從根結(jié)點(diǎn)到這個(gè)結(jié)點(diǎn)的字符串。它的存在是為了簡(jiǎn)化查詢(xún)。

Algorithms Fourth Edition
Written By Robert Sedgewick & Kevin Wayne
Translated By 謝路云
Chapter 5 Section 2 單詞查找樹(shù)

查找所需要的單詞的時(shí)間和鍵的長(zhǎng)度成正比

查找未命中只需檢查若干個(gè)單詞

單詞查找樹(shù) 單詞查找樹(shù)API

基本性質(zhì)

每個(gè)鏈接對(duì)應(yīng)一個(gè)字符

每個(gè)結(jié)點(diǎn)可能有一個(gè)值

有值,說(shuō)明存在從根結(jié)點(diǎn)到這個(gè)結(jié)點(diǎn)的字符串。

沒(méi)有值,說(shuō)明不存在從根結(jié)點(diǎn)到這個(gè)結(jié)點(diǎn)的字符串。沒(méi)有對(duì)應(yīng)的鍵值。它的存在是為了簡(jiǎn)化查詢(xún)。

查找

命中: 對(duì)應(yīng)結(jié)點(diǎn)有值(注意不單單是指向該對(duì)應(yīng)結(jié)點(diǎn)d鏈接存在,并且該結(jié)點(diǎn)一定要有值!)

未命中: 沒(méi)有值 or 鏈接為空

結(jié)點(diǎn)的表示

每個(gè)結(jié)點(diǎn)下面有R個(gè)鏈接,一個(gè)鏈接對(duì)應(yīng)一個(gè)字符

鍵隱式地保存在結(jié)點(diǎn)里

TrieST 代碼
public class TrieST {
    private static int R = 256; // radix
    private Node root; // root of trie

    private static class Node {
        private Object val;
        private Node[] next = new Node[R];
    }

    public Value get(String key) {
        Node x = get(root, key, 0);
        if (x == null)
            return null;
        return (Value) x.val;
    }
    
    // Return value associated with key in the subtrie rooted at x.
    private Node get(Node x, String key, int d) { 
        if (x == null)
            return null;
        if (d == key.length())
            return x;
        char c = key.charAt(d); // Use dth key char to identify subtrie.
        return get(x.next[c], key, d + 1);
    }

    public void put(String key, Value val) {
        root = put(root, key, val, 0);
    }
    
    // Change value associated with key if in subtrie rooted at x.
    private Node put(Node x, String key, Value val, int d) { //神一般的遞歸思想
        if (x == null)
            x = new Node();
        if (d == key.length()) {
            x.val = val;
            return x;
        }
        char c = key.charAt(d); // Use dth key char to identify subtrie.
        x.next[c] = put(x.next[c], key, val, d + 1); //神來(lái)之筆
        return x;
    }

    public Iterable keys() {
        return keysWithPrefix("");
    }

    public Iterable keysWithPrefix(String pre) {
        Queue q = new Queue();
        collect(get(root, pre, 0), pre, q);
        return q;
    }

    private void collect(Node x, String pre, Queue q) {
        if (x == null)
            return;
        if (x.val != null)
            q.enqueue(pre);
        for (char c = 0; c < R; c++) //這個(gè)效率簡(jiǎn)直了。。。爛到爆炸
            collect(x.next[c], pre + c, q);
    }
}

方法keys:返回一個(gè)Queue,里面有所有的字符串

方法keysWithPrefix(String pre):返回一個(gè)Queue,里面有所有以給定字符串pre開(kāi)頭的所有字符串

方法collect:遞歸用

通配符匹配

結(jié)構(gòu)差異

不含通配符的結(jié)構(gòu)。keysWithPrefix(); get(); collect();

含通配符的結(jié)構(gòu)。keysWithPrefix(); collect();

為什么結(jié)構(gòu)和之前不一樣呢?因?yàn)間et方法要重寫(xiě)。直接把重寫(xiě)的get方法歸并進(jìn)collect方法里去了。

    public Iterable keysThatMatch(String pat) {
        Queue q = new Queue();
        collect(root, "", pat, q);
        return q;
    }

    public void collect(Node x, String pre, String pat, Queue q) {
        int d = pre.length(); 
        // begin修改于原get方法()和collect方法()
        if (x == null) // get&collect
            return;
        if (d == pat.length() && x.val != null) // 前collect,后get
            q.enqueue(pre);
        if (d == pat.length())// get
            return; 
        // end 修改于原get方法()和collect方法()
        
        char next = pat.charAt(d);
        for (char c = 0; c < R; c++)
            if (next == "." || next == c) //如果next=="." 就要遍歷接在當(dāng)前字符后面的所有字符!??!
                collect(x.next[c], pre + c, pat, q); //還是神一般的遞歸想法
    }
private Node get(Node x, String key, int d) { 
        if (x == null)
            return null;
        if (d == key.length())
            return x;
        char c = key.charAt(d); // Use dth key char to identify subtrie.
        return get(x.next[c], key, d + 1);
    }
最長(zhǎng)前綴
    public String longestPrefixOf(String s) {
        int length = search(root, s, 0, 0);
        return s.substring(0, length);
    }

    //當(dāng)前搜索的是第d位字符,返回的是具有最長(zhǎng)length位前綴的子字符
    private int search(Node x, String s, int d, int length) {
        if (x == null) // 查到單詞樹(shù)的盡頭了
            return length;
        if (x.val != null) // 如果存在這個(gè)單詞,就更新length值
            length = d;
        if (d == s.length()) // 查到字符串的盡頭了(一定要先做上一步)
            return length;
        char c = s.charAt(d);
        return search(x.next[c], s, d + 1, length); //遞歸搜索下一位
    }
刪除操作

依舊是神一般的遞歸思路

如果它的鏈接不為空

刪去這個(gè)結(jié)點(diǎn)的即可

如果它的所有鏈接都為空

刪去這個(gè)結(jié)點(diǎn)

檢查這個(gè)結(jié)點(diǎn)的父結(jié)點(diǎn)的所有鏈接是否為空

不為空,結(jié)束

為空,刪去父結(jié)點(diǎn)并檢查父結(jié)點(diǎn)的父結(jié)點(diǎn)是否為空
……循環(huán)如此

    public void delete(String key) {
        root = delete(root, key, 0);
    }

    private Node delete(Node x, String key, int d) {
        if (x == null)
            return null;
        if (d == key.length()) //找到了的話(huà)就將該結(jié)點(diǎn)的值刪去
            x.val = null;
        else {
            char c = key.charAt(d);
            x.next[c] = delete(x.next[c], key, d + 1); //依舊是神一般的遞歸思路
        }
        if (x.val != null) //如果該結(jié)點(diǎn)有值,則不管當(dāng)前結(jié)點(diǎn)鏈接是否為空,該結(jié)點(diǎn)都在樹(shù)里,不能被刪去。
            return x;
        for (char c = 0; c < R; c++) //否則就看該結(jié)點(diǎn)鏈接是否為空(即該結(jié)點(diǎn)沒(méi)有值)
            if (x.next[c] != null) //如果當(dāng)前結(jié)點(diǎn)鏈接不為空,則返回當(dāng)前結(jié)點(diǎn)
                return x; 
        return null; //否則返回為空。(因?yàn)槭欠祷厣弦粚舆f歸, 即把自己置為空,也即刪除了自己)
    }
復(fù)雜度

字母表大小為R,N個(gè)隨機(jī)鍵組成的單詞查找樹(shù)中

時(shí)間:

查找和插入最差時(shí)間為:鍵的長(zhǎng)度+1

查找未命中的平均時(shí)間為:logRN (查找未命中的時(shí)間和鍵的長(zhǎng)度無(wú)關(guān)

空間

與 R和所有鍵的字符總數(shù)之積 成正比

鏈接

一棵單詞查找樹(shù)的鏈接總數(shù)為RN到RNw之間,w為鍵的平均長(zhǎng)度

當(dāng)所有鍵較短時(shí),鏈接總數(shù)接近RN

當(dāng)所有鍵較長(zhǎng)時(shí),鏈接總數(shù)接近RNw

縮小R能節(jié)省大量空間

三向單詞查找樹(shù)

避免空間消耗

每個(gè)結(jié)點(diǎn)含有一個(gè)字符,三個(gè)鏈接(小于,等于,大于),可能含有一個(gè)值

字符是顯式保存在每個(gè)結(jié)點(diǎn)中

TST 代碼
public class TST {
    private Node root; // root of trie

    private class Node {
        char c; // character
        Node left, mid, right; // left, middle, and right subtries
        Value val; // value associated with string
    }

    public Value get(String key) {
        Node x = get(root, key, 0);
        if (x == null)
            return null;
        return (Value) x.val;
    }

    private Node get(Node x, String key, int d) {
        if (x == null)
            return null;
        char c = key.charAt(d);
        if (c < x.c)
            return get(x.left, key, d);
        else if (c > x.c)
            return get(x.right, key, d);
        else if (d < key.length() - 1)
            return get(x.mid, key, d + 1);
        else
            return x;
    }

    public void put(String key, Value val) {
        root = put(root, key, val, 0);
    }

    private Node put(Node x, String key, Value val, int d) {
        char c = key.charAt(d);
        if (x == null) {
            x = new Node();
            x.c = c;
        }
        if (c < x.c)
            x.left = put(x.left, key, val, d);
        else if (c > x.c)
            x.right = put(x.right, key, val, d);
        else if (d < key.length() - 1)
            x.mid = put(x.mid, key, val, d + 1);
        else
            x.val = val;
        return x;
    }
}

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/66546.html

相關(guān)文章

  • 算法4Chapter 4.3 最小生成樹(shù)

    摘要:算法圖示代碼復(fù)雜度時(shí)間初始化優(yōu)先隊(duì)列,最壞情況次比較每次操作成本次比較,最多還會(huì)多次和次操作,但這些成本相比的增長(zhǎng)數(shù)量級(jí)可忽略不計(jì)詳見(jiàn)空間 Algorithms Fourth EditionWritten By Robert Sedgewick & Kevin WayneTranslated By 謝路云Chapter 4 Section 3 最小生成樹(shù) 定義 樹(shù)是特殊的圖 圖的生...

    asoren 評(píng)論0 收藏0
  • 算法4Chapter 4.2 強(qiáng)聯(lián)通性 Tarjan算法補(bǔ)充

    摘要:在實(shí)際的測(cè)試中,算法的運(yùn)行效率也比算法高左右。此外,該算法與求無(wú)向圖的雙連通分量割點(diǎn)橋的算法也有著很深的聯(lián)系。學(xué)習(xí)該算法,也有助于深入理解求雙連通分量的算法,兩者可以類(lèi)比組合理解。固屬于同一連通分支。 參考資料http://blog.csdn.net/acmmmm/a...https://www.byvoid.com/blog/s...http://blog.csdn.net/noth...

    maybe_009 評(píng)論0 收藏0
  • 算法4Chapter 1

    摘要:由的位置決定乘以幾,依次為,,,,,。遞歸算法遞歸算法就是本次結(jié)果用另外的參數(shù)調(diào)用自己。然而這個(gè)函數(shù)方法本身并沒(méi)有用,因?yàn)榉椒ㄖ腥魝鬟f參數(shù)為基本型如,在方法中對(duì)其值的改變并不會(huì)在主函數(shù)中產(chǎn)生影響。 Algorithms Fourth EditionWritten By Robert Sedgewick & Kevin WayneTranslated By 謝路云 筆記 二分查找 Bin...

    Jacendfeng 評(píng)論0 收藏0
  • 算法4Chapter 4.4 最短路徑

    摘要:相關(guān)操作就是判斷的不等號(hào)符號(hào)改反,初始值設(shè)為負(fù)無(wú)窮副本的最短路徑即為原圖的最長(zhǎng)路徑。方法是同上面一樣構(gòu)造圖,同時(shí)會(huì)添加負(fù)權(quán)重邊,再將所有邊取反,然后求最短路徑最短路徑存在則可行沒(méi)有負(fù)權(quán)重環(huán)就是可行的調(diào)度。 Algorithms Fourth EditionWritten By Robert Sedgewick & Kevin WayneTranslated By 謝路云Chapter ...

    leap_frog 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<