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

資訊專欄INFORMATION COLUMN

AVL樹的Java實(shí)現(xiàn)

leejan97 / 632人閱讀

摘要:容忍不平衡紅黑樹的思路的核心是增大了可容忍的高度差,從而實(shí)現(xiàn)既保證查詢效率,也保證了插入和刪除后調(diào)整平衡的效率。紅黑樹的查詢效率是略低于樹的,但是紅黑樹通過犧牲了少許查詢效率,使插入刪除后的調(diào)整效率達(dá)到了常數(shù)級(jí)別。

定義

Wikipedia - AVL樹

在計(jì)算機(jī)科學(xué)中,AVL樹是最早被發(fā)明的自平衡二叉查找樹。在AVL樹中,任一節(jié)點(diǎn)對(duì)應(yīng)的兩棵子樹的最大高度差為1,因此它也被稱為高度平衡樹。查找、插入和刪除在平均和最壞情況下的時(shí)間復(fù)雜度都是 {displaystyle O(log {n})} O(log{n})。增加和刪除元素的操作則可能需要借由一次或多次樹旋轉(zhuǎn),以實(shí)現(xiàn)樹的重新平衡。AVL樹得名于它的發(fā)明者G. M. Adelson-Velsky和Evgenii Landis,他們?cè)?962年的論文《An algorithm for the organization of information》中公開了這一數(shù)據(jù)結(jié)構(gòu)。
理論

實(shí)現(xiàn)AVL樹的要點(diǎn)為:每次新增/刪除節(jié)點(diǎn)后判斷平衡性然后通過調(diào)整使整棵樹重新平衡

判斷平衡性:每次新增/刪除節(jié)點(diǎn)后,刷新受到影響的節(jié)點(diǎn)的高度,即可通過任一節(jié)點(diǎn)的左右子樹高度差判斷其平衡性

調(diào)整:通過對(duì)部分節(jié)點(diǎn)的父子關(guān)系的改變使樹重新平衡

實(shí)現(xiàn) 基本結(jié)構(gòu)
public class Tree> {

    private static final int MAX_HEIGHT_DIFFERENCE = 1;

    private Node root;

    class Node {

        KT key;

        Node left;

        Node right;

        int height = 1;

        public Node(KT key, Node left, Node right) {
            this.key = key;
            this.left = left;
            this.right = right;
        }
    }
}
插入(insert) 四種不平衡范型

對(duì)于任意一次插入所造成的不平衡,都可以簡(jiǎn)化為下述四種范型之一:

下面四張圖中的數(shù)字僅代表節(jié)點(diǎn)序號(hào),為了后文方便展示調(diào)整過程
4、5、6、7號(hào)節(jié)點(diǎn)代表了四棵高度可以使不平衡成立的子樹(遵循插入的規(guī)則)

LL型

LR型

RR型

RL型

總結(jié)得到判斷范型的方法為:不平衡的節(jié)點(diǎn)(節(jié)點(diǎn)1)通往高度最大的子樹的葉子節(jié)點(diǎn)時(shí)所途經(jīng)的前兩個(gè)節(jié)點(diǎn)(節(jié)點(diǎn)2、節(jié)點(diǎn)3)的方向

調(diào)整方法

LL型

5號(hào)節(jié)點(diǎn)作為1號(hào)節(jié)點(diǎn)的左孩子

1號(hào)節(jié)點(diǎn)作為2號(hào)節(jié)點(diǎn)的右孩子

例子(例子中的數(shù)字代表節(jié)點(diǎn)的值):

插入節(jié)點(diǎn)5后造成節(jié)點(diǎn)9不平衡,其范型為LL型,按照固定步驟調(diào)整后全局重新達(dá)到平衡

LR型

6號(hào)節(jié)點(diǎn)作為2號(hào)節(jié)點(diǎn)的右孩子

7號(hào)節(jié)點(diǎn)作為1號(hào)節(jié)點(diǎn)的左孩子

2號(hào)節(jié)點(diǎn)作為3號(hào)節(jié)點(diǎn)的左孩子

1號(hào)節(jié)點(diǎn)作為3號(hào)節(jié)點(diǎn)的右孩子

例子(例子中的數(shù)字代表節(jié)點(diǎn)的值):

插入節(jié)點(diǎn)8.5后造成節(jié)點(diǎn)9不平衡,其范型為LR型,按照固定步驟調(diào)整后全局重新達(dá)到平衡

RR型

5號(hào)節(jié)點(diǎn)作為1號(hào)節(jié)點(diǎn)的右孩子

1號(hào)節(jié)點(diǎn)作為2號(hào)節(jié)點(diǎn)的左孩子

例子(例子中的數(shù)字代表節(jié)點(diǎn)的值):

插入節(jié)點(diǎn)10.5后造成節(jié)點(diǎn)7不平衡,其范型為RR型,按照固定步驟調(diào)整后全局重新達(dá)到平衡

RL型

7號(hào)節(jié)點(diǎn)作為2號(hào)節(jié)點(diǎn)的左孩子

6號(hào)節(jié)點(diǎn)作為1號(hào)節(jié)點(diǎn)的右孩子

2號(hào)節(jié)點(diǎn)作為3號(hào)節(jié)點(diǎn)的右孩子

1號(hào)節(jié)點(diǎn)作為3號(hào)節(jié)點(diǎn)的左孩子

例子(例子中的數(shù)字代表節(jié)點(diǎn)的值):

插入節(jié)點(diǎn)7.5后造成節(jié)點(diǎn)7不平衡,其范型為RL型,按照固定步驟調(diào)整后全局重新達(dá)到平衡

代碼實(shí)現(xiàn)
public void insert(T key) {
    if (key == null) {
        throw new NullPointerException();
    }
    root = insert(root, key);
}

private Node insert(Node node, T key) {
    if (node == null) {
        return new Node<>(key, null, null);
    }

    int cmp = key.compareTo(node.key);
    if (cmp == 0) {
        return node;
    }
    if (cmp < 0) {
        node.left = insert(node.left, key);
    } else {
        node.right = insert(node.right, key);
    }

    if (Math.abs(height(node.left) - height(node.right)) > MAX_HEIGHT_DIFFERENCE) {
        node = balance(node);
    }
    refreshHeight(node);
    return node;
}

private int height(Node node) {
    if (node == null) {
        return 0;
    }
    return node.height;
}

private void refreshHeight(Node node) {
    node.height = Math.max(height(node.left), height(node.right)) + 1;
}

/**
 * 此方法中的node, node1, node2分別代表上文范型中的1、2、3號(hào)節(jié)點(diǎn)
 */
private Node balance(Node node) {
    Node node1, node2;
    // ll
    if (height(node.left) > height(node.right) &&
            height(node.left.left) > height(node.left.right)) {
        node1 = node.left;
        node.left = node1.right;
        node1.right = node;

        refreshHeight(node);
        return node1;
    }
    // lr
    if (height(node.left) > height(node.right) &&
            height(node.left.right) > height(node.left.left)) {
        node1 = node.left;
        node2 = node.left.right;
        node.left = node2.right;
        node1.right = node2.left;
        node2.left = node1;
        node2.right = node;

        refreshHeight(node);
        refreshHeight(node1);
        return node2;
    }
    // rr
    if (height(node.right) > height(node.left) &&
            height(node.right.right) > height(node.right.left)) {
        node1 = node.right;
        node.right = node1.left;
        node1.left = node;

        refreshHeight(node);
        return node1;
    }
    // rl
    if (height(node.right) > height(node.left) &&
            height(node.right.left) > height(node.right.right)) {
        node1 = node.right;
        node2 = node.right.left;
        node.right = node2.left;
        node1.left = node2.right;
        node2.left = node;
        node2.right = node1;

        refreshHeight(node);
        refreshHeight(node1);
        return node2;
    }
    return node;
}
總結(jié)

由插入節(jié)點(diǎn)導(dǎo)致的局部不平衡均會(huì)符合上述四種范型之一,只需要按照固定的方式調(diào)整相關(guān)節(jié)點(diǎn)的父子關(guān)系即可使樹恢復(fù)平衡

關(guān)于調(diào)整,很多博客或者書籍中將這種調(diào)整父子關(guān)系的過程稱為旋轉(zhuǎn),這個(gè)就見仁見智了,個(gè)人覺得這種描述并不容易理解,故本文統(tǒng)一稱為調(diào)整

刪除(remove) 通常情況

對(duì)于刪除節(jié)點(diǎn)這個(gè)操作來說,有兩個(gè)要點(diǎn):被刪除節(jié)點(diǎn)的空缺應(yīng)該如何填補(bǔ)以及刪除后如何使樹恢復(fù)平衡

被刪除節(jié)點(diǎn)的空缺應(yīng)該如何填補(bǔ)

如果被刪除節(jié)點(diǎn)是葉子節(jié)點(diǎn),則不需要填補(bǔ)空缺

而如果是枝干節(jié)點(diǎn),則需要填補(bǔ)空缺,理想的情況是使用某個(gè)節(jié)點(diǎn)填補(bǔ)被刪除節(jié)點(diǎn)的空缺后,整棵樹仍然保持平衡
a) 如果節(jié)點(diǎn)的左右子樹有一棵為空,則使用非空子樹填補(bǔ)空缺
b) 如果節(jié)點(diǎn)的左右子樹均為非空子樹,則使用節(jié)點(diǎn)的左右子樹中更高的那棵子樹中的最大/最小節(jié)點(diǎn)來填補(bǔ)空缺(如果子樹高度一致則哪邊都可以)

例子:

假設(shè)待刪除節(jié)點(diǎn)為節(jié)點(diǎn)9,則應(yīng)當(dāng)使用左子樹中的最大值節(jié)點(diǎn)8來填補(bǔ)空缺

假設(shè)待刪除節(jié)點(diǎn)為節(jié)點(diǎn)13,則應(yīng)當(dāng)使用右子樹中的最小值節(jié)點(diǎn)14來填補(bǔ)空缺

假設(shè)待刪除節(jié)點(diǎn)為節(jié)點(diǎn)2,則使用左子樹中的最大值節(jié)點(diǎn)1.5或者右子樹中的最小值節(jié)點(diǎn)2.5來填補(bǔ)空缺均可

按照上述方式來填補(bǔ)空缺,可以盡可能保證刪除后整棵樹仍然保持平衡

刪除后如何使樹恢復(fù)平衡

如圖,葉子節(jié)點(diǎn)12為被刪除節(jié)點(diǎn),刪除后不需要填補(bǔ)空缺,但是此時(shí)節(jié)點(diǎn)13產(chǎn)生了不平衡

不過節(jié)點(diǎn)13的不平衡滿足上文所說的不平衡范型中的RR型,因此只需要對(duì)節(jié)點(diǎn)13做對(duì)應(yīng)的調(diào)整即可,如圖:

此時(shí)節(jié)點(diǎn)13所在的子樹經(jīng)過調(diào)整重新達(dá)到局部平衡

但是我們緊接著發(fā)現(xiàn),節(jié)點(diǎn)11出現(xiàn)了不平衡,其左子樹高度為4,右子樹高度為2

如果此時(shí)按照插入情況下的不平衡范型判斷方法去判斷節(jié)點(diǎn)11的不平衡情況屬于哪種范型,會(huì)發(fā)現(xiàn)無法滿足四種范型的任一情況

特殊情況

由刪除節(jié)點(diǎn)導(dǎo)致的不平衡,除了會(huì)出現(xiàn)插入中所說的四種范型之外,還會(huì)出現(xiàn)兩種情況,如圖:

整棵樹初始狀態(tài)為平衡狀態(tài),此時(shí)假設(shè)刪除節(jié)點(diǎn)13節(jié)點(diǎn)14,均會(huì)導(dǎo)致節(jié)點(diǎn)11產(chǎn)生不平衡(左子樹高度3,右子樹高度1)

但是如果仍然按照插入時(shí)的方法來判斷不平衡,則會(huì)發(fā)現(xiàn),節(jié)點(diǎn)4的左右子樹高度一致,即在滿足了L后,后續(xù)無法判斷這種情況屬于哪種范型

對(duì)于R方向也是一樣

本文稱它們?yōu)?b>L型和R型

不過這兩種情況的處理也很簡(jiǎn)單,實(shí)際上當(dāng)出現(xiàn)這種情況時(shí),使用LL型LR型的調(diào)整方法均可以達(dá)到使樹重新平衡的目的

如圖:

兩種調(diào)整方式均可使樹重新平衡,對(duì)于R型也是一樣,這里不再贅述

代碼實(shí)現(xiàn)
public void remove(T key) {
    if (key == null) {
        throw new NullPointerException();
    }
    root = remove(root, key);
}

private Node remove(Node node, T key) {
    if (node == null) {
        return null;
    }

    int cmp = key.compareTo(node.key);
    if (cmp < 0) {
        node.left = remove(node.left, key);
    }
    if (cmp > 0){
        node.right = remove(node.right, key);
    }
    if (cmp == 0) {
        if (node.left == null || node.right == null) {
            return node.left == null ? node.right : node.left;
        }
        var successorKey = successorOf(node).key;
        node = remove(node, successorKey);
        node.key = successorKey;
    }

    if (Math.abs(height(node.left) - height(node.right)) > MAX_HEIGHT_DIFFERENCE) {
        node = balance(node);
    }
    refreshHeight(node);
    return node;
}

/**
 * 尋找被刪除節(jié)點(diǎn)的繼承者
 */
private Node successorOf(Node node) {
    if (node == null) {
        throw new NullPointerException();
    }
    if (node.left == null || node.right == null) {
        return node.left == null ? node.right : node.left;
    }

    return height(node.left) > height(node.right) ?
            findMax(node.left, node.left.right, node.left.right == null) :
            findMin(node.right, node.right.left, node.right.left == null);
}

private Node findMax(Node node, Node right, boolean rightIsNull) {
    if (rightIsNull) {
        return node;
    }
    return findMax((node = right), node.right, node.right == null);
}

private Node findMin(Node node, Node left, boolean leftIsNull) {
    if (leftIsNull) {
        return node;
    }
    return findMin((node = left), node.left, node.left == null);
}

其中用到的private Node balance(Node node)方法修改為:

private Node balance(Node node) {
    Node node1, node2;
    // ll & l
    if (height(node.left) > height(node.right) &&
            height(node.left.left) >= height(node.left.right)) {
        node1 = node.left;
        node.left = node1.right;
        node1.right = node;

        refreshHeight(node);
        return node1;
    }
    // lr
    if (height(node.left) > height(node.right) &&
            height(node.left.right) > height(node.left.left)) {
        node1 = node.left;
        node2 = node.left.right;
        node.left = node2.right;
        node1.right = node2.left;
        node2.left = node1;
        node2.right = node;

        refreshHeight(node);
        refreshHeight(node1);
        return node2;
    }
    // rr & r
    if (height(node.right) > height(node.left) &&
            height(node.right.right) >= height(node.right.left)) {
        node1 = node.right;
        node.right = node1.left;
        node1.left = node;

        refreshHeight(node);
        return node1;
    }
    // rl
    if (height(node.right) > height(node.left) &&
            height(node.right.left) > height(node.right.right)) {
        node1 = node.right;
        node2 = node.right.left;
        node.right = node2.left;
        node1.left = node2.right;
        node2.left = node;
        node2.right = node1;

        refreshHeight(node);
        refreshHeight(node1);
        return node2;
    }
    return node;
}

也就是將L型情況包含進(jìn)了LL型R型的情況包含進(jìn)了RR型,因?yàn)檫@兩種范式的調(diào)整要比對(duì)應(yīng)的LR型/RL型的操作數(shù)少

總結(jié)

盡管刪除節(jié)點(diǎn)時(shí)會(huì)出現(xiàn)特殊的情況,但是仍然可以通過簡(jiǎn)單的調(diào)整使樹始終保持平衡

完整代碼
/**
 * AVL-Tree
 *
 * @author Shinobu
 * @since 2019/5/7
 */
public class Tree> {

    private static final int MAX_HEIGHT_DIFFERENCE = 1;

    private Node root;

    class Node {

        KT key;

        Node left;

        Node right;

        int height = 1;

        public Node(KT key, Node left, Node right) {
            this.key = key;
            this.left = left;
            this.right = right;
        }
    }

    public Tree(T... keys) {
        if (keys == null || keys.length < 1) {
            throw new NullPointerException();
        }

        root = new Node<>(keys[0], null, null);
        for (int i = 1; i < keys.length && keys[i] != null; i++) {
            root = insert(root, keys[i]);
        }
    }

    public T find(T key) {
        if (key == null || root == null) {
            return null;
        }
        return find(root, key, key.compareTo(root.key));
    }

    private T find(Node node, T key, int cmp) {
        if (node == null) {
            return null;
        }

        if (cmp == 0) {
            return node.key;
        }

        return find(
                (node = cmp > 0 ? node.right : node.left),
                key,
                node == null ? 0 : key.compareTo(node.key));
    }

    public void insert(T key) {
        if (key == null) {
            throw new NullPointerException();
        }
        root = insert(root, key);
    }

    private Node insert(Node node, T key) {
        if (node == null) {
            return new Node<>(key, null, null);
        }

        int cmp = key.compareTo(node.key);
        if (cmp == 0) {
            return node;
        }
        if (cmp < 0) {
            node.left = insert(node.left, key);
        } else {
            node.right = insert(node.right, key);
        }

        if (Math.abs(height(node.left) - height(node.right)) > MAX_HEIGHT_DIFFERENCE) {
            node = balance(node);
        }
        refreshHeight(node);
        return node;
    }

    private int height(Node node) {
        if (node == null) {
            return 0;
        }
        return node.height;
    }

    private void refreshHeight(Node node) {
        node.height = Math.max(height(node.left), height(node.right)) + 1;
    }

    private Node balance(Node node) {
        Node node1, node2;
        // ll & l
        if (height(node.left) > height(node.right) &&
                height(node.left.left) >= height(node.left.right)) {
            node1 = node.left;
            node.left = node1.right;
            node1.right = node;

            refreshHeight(node);
            return node1;
        }
        // lr
        if (height(node.left) > height(node.right) &&
                height(node.left.right) > height(node.left.left)) {
            node1 = node.left;
            node2 = node.left.right;
            node.left = node2.right;
            node1.right = node2.left;
            node2.left = node1;
            node2.right = node;

            refreshHeight(node);
            refreshHeight(node1);
            return node2;
        }
        // rr & r
        if (height(node.right) > height(node.left) &&
                height(node.right.right) >= height(node.right.left)) {
            node1 = node.right;
            node.right = node1.left;
            node1.left = node;

            refreshHeight(node);
            return node1;
        }
        // rl
        if (height(node.right) > height(node.left) &&
                height(node.right.left) > height(node.right.right)) {
            node1 = node.right;
            node2 = node.right.left;
            node.right = node2.left;
            node1.left = node2.right;
            node2.left = node;
            node2.right = node1;

            refreshHeight(node);
            refreshHeight(node1);
            return node2;
        }
        return node;
    }

    public void remove(T key) {
        if (key == null) {
            throw new NullPointerException();
        }
        root = remove(root, key);
    }

    private Node remove(Node node, T key) {
        if (node == null) {
            return null;
        }

        int cmp = key.compareTo(node.key);
        if (cmp < 0) {
            node.left = remove(node.left, key);
        }
        if (cmp > 0){
            node.right = remove(node.right, key);
        }
        if (cmp == 0) {
            if (node.left == null || node.right == null) {
                return node.left == null ? node.right : node.left;
            }
            var successorKey = successorOf(node).key;
            node = remove(node, successorKey);
            node.key = successorKey;
        }

        if (Math.abs(height(node.left) - height(node.right)) > MAX_HEIGHT_DIFFERENCE) {
            node = balance(node);
        }
        refreshHeight(node);
        return node;
    }
    
    private Node successorOf(Node node) {
        if (node == null) {
            throw new NullPointerException();
        }
        if (node.left == null || node.right == null) {
            return node.left == null ? node.right : node.left;
        }

        return height(node.left) > height(node.right) ?
                findMax(node.left, node.left.right, node.left.right == null) :
                findMin(node.right, node.right.left, node.right.left == null);
    }

    private Node findMax(Node node, Node right, boolean rightIsNull) {
        if (rightIsNull) {
            return node;
        }
        return findMax((node = right), node.right, node.right == null);
    }

    private Node findMin(Node node, Node left, boolean leftIsNull) {
        if (leftIsNull) {
            return node;
        }
        return findMin((node = left), node.left, node.left == null);
    }

}
結(jié)語

AVL樹的實(shí)現(xiàn),在了解了不平衡的六種情況,以及對(duì)應(yīng)的處理方式后,還是比較簡(jiǎn)單且邏輯清晰的

通過對(duì)AVL樹的學(xué)習(xí),可以發(fā)現(xiàn)它是一種“對(duì)不平衡非常敏感”的結(jié)構(gòu)——可以容忍的高度差僅為1。這雖然可以讓樹盡可能的平衡,使查找效率盡可能高,但也付出了相應(yīng)的代價(jià): 調(diào)整平衡。

它的插入元素引發(fā)的調(diào)整的最壞時(shí)間復(fù)雜度為O(1),但是刪除引發(fā)的最壞時(shí)間復(fù)雜度為O(logN),這正是AVL樹的弊端所在。

所以后來的2-3樹、2-3-4樹、紅黑樹都嘗試對(duì)這種弊端進(jìn)行了改進(jìn),改進(jìn)的思路可以大概理解為兩種:

使樹完全平衡
這是2-3樹和2-3-4樹這兩種結(jié)構(gòu)嘗試的方向。因?yàn)樵斐葾VL樹刪除時(shí)“雪崩”的原因正是因?yàn)樗苋萑痰倪@一點(diǎn)高度差,在高度差大量積累后,刪除“薄弱”側(cè)的節(jié)點(diǎn),就會(huì)導(dǎo)致需要大量的調(diào)整才能恢復(fù)平衡。而如果完全消除高度差,就可以避免這種情況了。
然而實(shí)際的情況是這兩種樹的實(shí)現(xiàn)都算不上簡(jiǎn)單,而且反而使插入的調(diào)整行為的時(shí)間復(fù)雜度變?yōu)榱薕(logN)。

容忍不平衡
紅黑樹的思路的核心是增大了可容忍的高度差,從而實(shí)現(xiàn)既保證查詢效率(O(logN)),也保證了插入和刪除后調(diào)整平衡的效率(O(1))。
紅黑樹的查詢效率(2 * O(logN))是略低于AVL樹(O(logN))的,但是紅黑樹通過犧牲了少許查詢效率,使插入刪除后的調(diào)整效率達(dá)到了常數(shù)級(jí)別。
紅黑樹算法中的著色策略、對(duì)于父節(jié)點(diǎn)、叔節(jié)點(diǎn)、祖父節(jié)點(diǎn)等等節(jié)點(diǎn)的顏色判斷、以及相應(yīng)的調(diào)整策略都是經(jīng)過極度抽象后的結(jié)果,因此想要從頭到尾徹底理解紅黑樹的設(shè)計(jì)思想其實(shí)還是有些難度的(理解設(shè)計(jì)思想并非照著抽象好的五條規(guī)則照本宣科)

以上,希望本文對(duì)讀到的朋友能有所幫助

文章如果有謬誤或疏漏,還請(qǐng)務(wù)必指正,感謝萬分

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

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

相關(guān)文章

  • 一文掌握關(guān)于Java數(shù)據(jù)結(jié)構(gòu)所有知識(shí)點(diǎn)(歡迎一起完善)

    摘要:是棧,它繼承于。滿二叉樹除了葉結(jié)點(diǎn)外每一個(gè)結(jié)點(diǎn)都有左右子葉且葉子結(jié)點(diǎn)都處在最底層的二叉樹。沒有鍵值相等的節(jié)點(diǎn)。這是數(shù)據(jù)庫(kù)選用樹的最主要原因。 在我們學(xué)習(xí)Java的時(shí)候,很多人會(huì)面臨我不知道繼續(xù)學(xué)什么或者面試會(huì)問什么的尷尬情況(我本人之前就很迷茫)。所以,我決定通過這個(gè)開源平臺(tái)來幫助一些有需要的人,通過下面的內(nèi)容,你會(huì)掌握系統(tǒng)的Java學(xué)習(xí)以及面試的相關(guān)知識(shí)。本來是想通過Gitbook的...

    keithxiaoy 評(píng)論0 收藏0
  • Python數(shù)據(jù)結(jié)構(gòu)——AVL樹的基本概念

    摘要:我們知道,當(dāng)樹變得不平衡時(shí)和操作會(huì)使二叉搜索樹的性能降低到。樹實(shí)現(xiàn)抽象數(shù)據(jù)類型就像一個(gè)普通的二叉搜索樹,唯一不同的是這棵樹的工作方式。我們通過比較每個(gè)節(jié)點(diǎn)的左右子樹的高度完成比較。 平衡二叉搜索樹 在上一節(jié)中我們討論了建立一個(gè)二叉搜索樹。我們知道,當(dāng)樹變得不平衡時(shí)get和put操作會(huì)使二叉搜索樹的性能降低到O(n)。在這一節(jié)中我們將看到一種特殊的二叉搜索樹,它可以自動(dòng)進(jìn)行調(diào)整,以確保樹...

    jiekechoo 評(píng)論0 收藏0
  • 學(xué)習(xí)JavaScript數(shù)據(jù)結(jié)構(gòu)與算法 — AVL

    摘要:可以看到,一次左單旋將右側(cè)子樹的高度減小了,而左側(cè)子樹的高度增加了。如圖,對(duì)進(jìn)行右單旋,需要左子樹的右子樹的高度小于等于左子樹的高度,否則不能達(dá)到平衡的效果,只是把不平衡性從左邊轉(zhuǎn)移到了右邊。 AVL樹 普通二叉搜索樹可能出現(xiàn)一條分支有多層,而其他分支卻只有幾層的情況,如圖1所示,這會(huì)導(dǎo)致添加、移除和搜索樹具有性能問題。因此提出了自平衡二叉樹的概念,AVL樹(阿德爾森-維爾斯和蘭迪斯樹...

    impig33 評(píng)論0 收藏0
  • 樹 - (二叉查找樹,紅黑樹,B樹)- 紅黑樹

    摘要:需要執(zhí)行的操作依次是首先,將紅黑樹當(dāng)作一顆二叉查找樹,將該節(jié)點(diǎn)從二叉查找樹中刪除然后,通過旋轉(zhuǎn)和重新著色等一系列來修正該樹,使之重新成為一棵紅黑樹。 雖是讀書筆記,但是如轉(zhuǎn)載請(qǐng)注明出處 http://segmentfault.com/blog/exploring/ .. 拒絕伸手復(fù)制黨 關(guān)于二叉樹的基本知識(shí),可以參見:Java 實(shí)現(xiàn)基本數(shù)據(jù)結(jié)構(gòu) 2(樹) 以下是算法導(dǎo)論第13章的學(xué)...

    yangrd 評(píng)論0 收藏0
  • Python數(shù)據(jù)結(jié)構(gòu)——AVL樹的實(shí)現(xiàn)

    摘要:一旦子樹平衡因子為零,那么父節(jié)點(diǎn)的平衡因子不會(huì)發(fā)生改變。新根的父節(jié)點(diǎn)將成為舊根的父節(jié)點(diǎn)。因?yàn)槠渌僮鞫际且苿?dòng)整個(gè)子樹,被移動(dòng)的子樹內(nèi)的節(jié)點(diǎn)的平衡因子不受旋轉(zhuǎn)的影響。讓表示以為根節(jié)點(diǎn)的子樹的高度。 既然,我們已經(jīng)證明,保持 AVL 樹的平衡將會(huì)使性能得到很大的提升,那我們看看如何在程序中向樹插入一個(gè)新的鍵值。因?yàn)樗械男骆I是作為葉節(jié)點(diǎn)插入樹的,而新葉子的平衡因子為零,所以我們對(duì)新插入的節(jié)...

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

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

0條評(píng)論

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