国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹

這篇具有很好參考價值的文章主要介紹了數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

所謂的AVL樹也叫做高度平衡的二叉搜索樹。

啥是高度平衡的二叉搜索樹?

高度平衡的二叉搜索樹:意味著左右子樹的高度最大不超過一。

我們先來回顧一下二叉搜索樹的概念:

二叉搜索樹又稱二叉排序樹,它或者是一棵空樹,或者是具有以下性質(zhì)的二叉樹:

  • 若它的左子樹不為空,則左子樹上所有節(jié)點的值都小于根節(jié)點的值
  • 若它的右子樹不為空,則右子樹上所有節(jié)點的值都大于根節(jié)點的值
  • 它的左右子樹也分別為二叉搜索樹

它或許是個完全二叉樹:

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

在極端情況下又是個單分支的樹:

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

一個二叉搜索樹的時間復(fù)雜度為:O(N),?極端情況下,例如上圖(左右單支)的情況,樹的高度很高,那么就會導(dǎo)致搜索的效率很低,如果此時有N個樹,樹的高度就為N。

所以我們需要一顆更高效的樹,這就是高度平衡的二叉搜索樹,這也就是為什么需要高度平衡的原因。

AVL樹的概念

二叉搜索樹雖可以縮短查找的效率,但如果數(shù)據(jù)有序或接近有序二叉搜索樹將退化為單支樹,查找元素相當于在順序表中搜索元素,效率低下。因此,兩位俄羅斯的數(shù)學(xué)家G.M.Adelson-Velskii和E.M.Landis在1962年 發(fā)明了一種解決上述問題的方法:當向二叉搜索樹中插入新結(jié)點后,如果能保證每個結(jié)點的左右子樹高度之差的絕對值不超過1(需要對樹中的結(jié)點進行調(diào)整),即可降低樹的高度,從而減少平均搜索長度。

一棵AVL樹或者是空樹,或者是具有以下性質(zhì)的二叉搜索樹:

  • 它的左右子樹都是AVL樹
  • 左右子樹高度之差(簡稱平衡因子)的絕對值不超過1(-1/0/1)

如圖:

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

?每個結(jié)點旁的數(shù)字代表著其平衡高度,左子樹存在一個為 -1,右子樹存在一個即為1,不存在則為0。

其中,3 結(jié)點上,左子樹的高度為2,所以左子樹的平衡因子應(yīng)該為 -2,右子樹的高度為1,所以右子樹的平衡因子為1,二者相結(jié)合的平衡因子應(yīng)該為:-1。

如果一棵二叉搜索樹是高度平衡的,它就是AVL樹。如果它有n個結(jié)點,其高度可保持在? ? ? ? ? ? ? O( logN),搜索時間復(fù)雜度O( logN)。

實現(xiàn)AVL樹的相關(guān)代碼

AVL樹節(jié)點的定義

AVL樹結(jié)點的定義其實很簡單:

static class TreeNode {
    public TreeNode left; // 節(jié)點的左孩子
    public TreeNode right; // 節(jié)點的右孩子
    public TreeNode parent ; // 節(jié)點的雙親
    public int val = 0;
    public int bf = 0; // 當前節(jié)點的平衡因子=右子樹高度-左子樹的高度
    public TreeNode(int val) {
        this.val = val;
    }
}

注意:
當前節(jié)點的平衡因子=右子樹高度-左子樹的高度。但是,不是每棵樹,都必須有平衡因子,這只是其中的一種實現(xiàn)方式。

AVL樹的插入

AVL樹就是在二叉搜索樹的基礎(chǔ)上引入了平衡因子,因此AVL樹也可以看成是二叉搜索樹。那么AVL樹的插入過程可以分為兩步:

  1. 按照二叉搜索樹的方式插入新結(jié)點
  2. 調(diào)節(jié)結(jié)點的平衡因子

這里我們畫圖一步步來講解。

我們先來隨便畫棵樹:

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

現(xiàn)在我們有這樣一棵AVL樹,我們給它插入一個 5 的結(jié)點。

還是和二叉搜索樹一樣去尋找,從根節(jié)點開始,大于根結(jié)點的值向右走,小于根節(jié)點的向左走,以此類推。

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

此時,我們需要重新調(diào)節(jié)平衡因子:

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

此時就需要對整棵樹進行一個旋轉(zhuǎn)。

樹的旋轉(zhuǎn)

右單旋

?既然它不平衡,那就需要想辦法讓他平衡。

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

??這里只是其中一種旋轉(zhuǎn),我們再來看看其他情況:

左單旋

我們現(xiàn)在有這樣一棵樹:

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

?我們新插入一個50:

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

此時,25 的結(jié)點就不平衡了,我們也需要旋轉(zhuǎn):

旋轉(zhuǎn)過后:

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)?由上述的兩種旋轉(zhuǎn)我們看到一個細節(jié):

?數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)??

  • 不平衡時,該不平衡的結(jié)點和其子節(jié)點的平衡因子必然同號,此時我們只需要單旋即可。
  • 并且,平衡因子為負數(shù)需要發(fā)送右旋,平衡因子為正數(shù)需要發(fā)生左旋
  • 如若,異號則需要發(fā)生雙旋

左右雙旋

我們還是以發(fā)生右單旋的圖為基礎(chǔ),我們現(xiàn)在不插入5,而是插入 28 ;

如圖:

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

?我們可以看出來:30 這個節(jié)點上的平衡因子和 20 這個節(jié)點上的平衡因子異號了。

無論是左單旋還是右單旋都無濟于事。不信可以自己去畫畫圖;

最終結(jié)果如圖所示:

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

?右左雙旋

?我們在左單旋的基礎(chǔ)上,插入一個值為 26 的結(jié)點,如下圖:

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

同樣的,無法用單旋來解決問題。

我們需要先右單旋在左單旋;如下圖:

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

ok,上面只是介紹了單旋是怎么旋轉(zhuǎn)的,接下來要開始講解代碼了。

代碼實現(xiàn)

插入方法代碼

首先,我們要將這個方法設(shè)置為布爾值類型,因為這個方法是有可能無法執(zhí)行的。

AVL樹是基于二叉搜索樹衍生的,二叉搜索樹中是無法實現(xiàn)插入相同的值。

所以這里的插入方法可以參考參考二叉搜索樹。

第一步,需要判斷根節(jié)點是否為空,為空那么這個需要插入的 val 就直接為根結(jié)點就行了。

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

第二步,開始遍歷,設(shè)置 一個 cur ,一個 parent ,兩個TreeNode ,去找目標 val 應(yīng)該要插入的位置。

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

ok,目前為止與二叉搜索樹沒有太大差別,我們到這里已經(jīng)找到了目標 val 應(yīng)該插入的為止,還需要解決 平衡因子和轉(zhuǎn)換后各個結(jié)點的關(guān)系。

此時的 node 已經(jīng)是葉子節(jié)點了

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)為啥這里的循環(huán)條件是parent !=?null,我們來看張旋轉(zhuǎn)圖:

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

我們圖中,30 是個根節(jié)點嗎?

它也可以是某個結(jié)點的子節(jié)點(故此,我們還需要向上平衡);直到調(diào)節(jié)到根結(jié)點才算調(diào)整完畢。?

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

?數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

兩兩對比,就能總結(jié)出規(guī)律了。?

public boolean insert(int val) {
        TreeNode node = new TreeNode(val);
        // 根節(jié)點為空
        if (root == null) {
            root = node;
            return true;
        }
        TreeNode parent = null;
        TreeNode cur = root;
        while (cur != null) {
            if (cur.val < val){
                parent = cur;
                cur = cur.right;
            } else if (cur.val == val) {
                return false;
            } else {
                parent = cur;
                cur = cur.left;
            }
        }
        // cur == null
        if (parent.val < val) {
            parent.right = node;
        } else {
            parent.left = node;
        }

        // 當前只是解決了 left 和 right ,還沒有處理 node 的 parent
        node.parent = parent;
        cur = node;

        // 調(diào)節(jié)平衡因子
        while (parent != null) {
            // 先看 cur 是 parent 的左還是右;此時決定了平衡因子是 ++ 還是 --
            if (cur == parent.right) {
                parent.bf++;
            } else{
                parent.bf--;
            }
            //檢查當前平衡因子是否絕對值 <= 1
            if (parent.bf == 0) {
                // 記住一個結(jié)論: cur 的 parent 的平衡因子為 0 ,
                // 那么它插入一個結(jié)點一定平衡,此時無論插入右子樹還是右子樹都無所謂,就不用往上繼續(xù)調(diào)節(jié)

                // 此時已經(jīng)平衡了
                break;
            } else if (parent.bf == 1 || parent.bf == -1) {
                // 此時插入一個結(jié)點,其父節(jié)點未必平衡,需要繼續(xù)向上調(diào)節(jié)
                cur = parent;
                parent = parent.parent;
            } else {
                if (parent.bf == 2) {
                    // 此時說明右樹高,需要先左旋,再右旋
                    if (cur.bf == 1) {
                        rotateLeft(parent);
                    } else {
                        // cur.bf == -1
                        rotateRL(parent);
                    }
                } else {
                    // cur.bf == -2 ;左樹高,需要降低左樹的高度
                    // 同樣也分平衡因子為 1 和 -1 兩種情況
                    if (cur.bf == -1) {
                        // 右旋
                        rotateRight(parent);
                    } else {
                        // cur.bf == 1
                        rotateLR(parent);
                    }
                }
                break;
            }
        }
        return true;
    }

右單旋

還是需要借助上述的案例來進行講解:

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

/**
     * 右單旋
     * @param parent
     */
    private void rotateLeft(TreeNode parent) {
        TreeNode subR = parent.right;
        TreeNode subRL = subR.left;

        // 旋轉(zhuǎn)關(guān)系 (需要畫圖)
        parent.right = subRL;
        subR.left = parent;
        if (subRL != null) { // subRL 可能為空
            subRL.parent = parent;
        }
        // 與左單旋一樣,需要判斷parent 所在的位置是根節(jié)點還是某個子樹
        TreeNode pParent = parent.parent;
        parent.parent = subR;

        // 為根節(jié)點的情況
        if (root == parent) {
            root = subR;
            root.parent = null;
        } else {
            // 不為根節(jié)點的情況
            if (pParent.left == parent) {
                pParent.left = subR;
            } else {
                pParent.right = subR;
            }
            subR.parent = pParent;
        }
        // 調(diào)節(jié)平衡因子
        subR.bf = parent.bf = 0;
    }

這里的parent 是需要插入的葉子結(jié)點的父節(jié)點。

我們首先需要保存一下需要調(diào)整位置的幾個結(jié)點:

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

第一步:先斷開parent 和 subR 之間的關(guān)系,建立subRL 和 parent 之間的關(guān)系:

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)?

第二步:斷開subR 和 subRL 之間的關(guān)系,建立subR 和 parent 之間的關(guān)系:

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)?

當然啦,subRL并非一定存在,它也可以不存在啊,不存在的情況需要特殊處理一下:

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)?

當然,我們目前只確定了彼此之間的left 和 right ,別忘了我們TreeNode 還定義了 parent,所以目前我們還需要處理一下父節(jié)點的問題。

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)?

如上圖,我們需要確定parent 這個結(jié)點的位置是否為 根節(jié)點,如果是根結(jié)點那么 subR 的父節(jié)點就是null,如果不是則需要確定具體是 pParent?哪邊:

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

ok,這里就是右單旋的代碼,接下來看看左單旋;

左單旋

具體代碼:

    /**
     * 左單旋
     * @param parent
     */
    private void rotateRight(TreeNode parent) {
        // 處理旋轉(zhuǎn)之后幾個節(jié)點的關(guān)系
        TreeNode subL = parent.left;
        TreeNode subLR = subL.right;
        parent.left = subLR;
        subL.right = parent;
        // subLR 是可能為空的,為空還進行就會報錯!
        if (subLR != null) {
            subLR.parent = parent;
        }
        // 必須先記錄父節(jié)點的父節(jié)點(這一段畫圖理解)
        TreeNode pParent = parent.parent;

        parent.parent = subL;
        // 判斷 parent 是否為 根節(jié)點
        if(parent == root) {
            root = subL;
            root.parent = null;
        } else {
            // 不是根結(jié)點,就判斷這棵樹是左子樹還是右子樹
            if (pParent.left == parent) {
                pParent.left = subL;
            } else {
                pParent.right = subL;
            }
        }
        // 全部調(diào)整完畢,還需要調(diào)節(jié) 平衡因子
        subL.bf = 0;
        parent.bf = 0;
    }

同樣的,我們得先保存幾個需要調(diào)整位置的結(jié)點,如下圖:

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

??我們先調(diào)整 幾個結(jié)點之間的left 和 right 的關(guān)系;

第一步,斷開parent 和 subL 之間的關(guān)系,連接 parent 和 subLR 的關(guān)系:

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

?第二步:斷開subL 和 subLR 的關(guān)系,連接 subL 和 parent 的關(guān)系:

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

同樣的,subLR并非一定存在,它也可以不存在啊,不存在的情況需要特殊處理一下:

?數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

?數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

接下來的操作都一樣:

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)?

?數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

右左雙旋

確實雙旋比單旋難不了多少,雙旋是建立在單旋的基礎(chǔ)上的,只需要單旋兩次即可。

先看示意圖:

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)?

    /**
     * 右左雙旋
     * @param parent
     */
    private void rotateLR(TreeNode parent) {
        TreeNode subL = parent.left;
        TreeNode subLR = subL.right;
        int bf = subLR.bf;
        rotateLeft(parent.left);
        rotateRight(parent);

        if (bf == -1) {
            subL.bf = 0;
            subLR.bf = 0;
            parent.bf = 1;
        } else {
            // bf == 1
            subL.bf = -1;
            subLR.bf = 0;
            parent.bf = 0;
        }
    }

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

?我們來看看這兩種情況:

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)

于是就變成了這樣:

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)?

此時的subLR 的平衡因子就是 -1 了,所以需要保留一下sunLR的平衡因子;

旋轉(zhuǎn)還是一樣的旋轉(zhuǎn),只是旋轉(zhuǎn)以后需要改變不同的平衡因子:

數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹,數(shù)據(jù)結(jié)構(gòu)高階,數(shù)據(jù)結(jié)構(gòu)?

同樣的,?左右雙旋也是同理。

這里就不單獨介紹左右雙旋,可以自己畫個圖,然后參考上面右左雙旋的做法。

此外還有一個刪除沒有了解,過后我在此處補齊。

完整代碼:

AVLTree/src/AVLTree.java · wjm的碼云/Projects - 碼云 - 開源中國 (gitee.com)文章來源地址http://www.zghlxwxcb.cn/news/detail-529145.html

到了這里,關(guān)于數(shù)據(jù)結(jié)構(gòu)進階(一):AVL樹的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 數(shù)據(jù)結(jié)構(gòu)之進階二叉樹(二叉搜索樹和AVL樹、紅黑樹的實現(xiàn))超詳細解析,附實操圖和搜索二叉樹的實現(xiàn)過程圖

    數(shù)據(jù)結(jié)構(gòu)之進階二叉樹(二叉搜索樹和AVL樹、紅黑樹的實現(xiàn))超詳細解析,附實操圖和搜索二叉樹的實現(xiàn)過程圖

    緒論? “生命有如鐵砧,愈被敲打,愈能發(fā)出火花?!だ浴?;本章主要是數(shù)據(jù)結(jié)構(gòu) 二叉樹的進階知識,若之前沒學(xué)過二叉樹建議看看這篇文章一篇掌握二叉樹,本章的知識從淺到深的 對搜索二叉樹的使用進行了介紹和對其底層邏輯的實現(xiàn)進行了講解 ,希望能對你有所

    2024年02月04日
    瀏覽(28)
  • 【數(shù)據(jù)結(jié)構(gòu)】AVL 樹

    【數(shù)據(jù)結(jié)構(gòu)】AVL 樹

    前面對 map / multimap / set / multiset 進行了簡單的介紹【C++】map set,在其文檔介紹中發(fā)現(xiàn),這幾個容器有個共同點是: 其底層都是按照二叉搜索樹來實現(xiàn)的 ,但是二叉搜索樹有其自身的缺陷,假如往樹中插入的元素有序或者接近有序,二叉搜索樹就會退化成單支樹,時間復(fù)雜度

    2024年04月12日
    瀏覽(19)
  • 【數(shù)據(jù)結(jié)構(gòu)】AVL樹

    【數(shù)據(jù)結(jié)構(gòu)】AVL樹

    ??作者:一只大喵咪1201 ??專欄:《數(shù)據(jù)結(jié)構(gòu)與算法》 ??格言: 你只管努力,剩下的交給時間! 我們知道,二叉搜索樹的搜索效率非常高,平均時間復(fù)雜度是O(log 2 N),但是當數(shù)據(jù)原本就有序時,插入二叉樹中就會形成單支結(jié)構(gòu),此時搜索的時間復(fù)雜度就是O(N)。 為了避免

    2023年04月18日
    瀏覽(24)
  • [數(shù)據(jù)結(jié)構(gòu)]-AVL樹

    [數(shù)據(jù)結(jié)構(gòu)]-AVL樹

    前言 作者:小蝸牛向前沖 名言:我可以接受失敗,但我不能接受放棄 ??如果覺的博主的文章還不錯的話,還請 點贊,收藏,關(guān)注??支持博主。如果發(fā)現(xiàn)有問題的地方歡迎?大家在評論區(qū)指正 目錄 一、AVL樹基本知識 1、概念 2、節(jié)點定義 3、插入 二、AVL樹的旋轉(zhuǎn) 1、右單旋

    2024年02月04日
    瀏覽(24)
  • C++&&數(shù)據(jù)結(jié)構(gòu)——AVL樹

    C++&&數(shù)據(jù)結(jié)構(gòu)——AVL樹

    根據(jù)前面對二叉搜索樹的學(xué)習(xí)我們可以了解到二叉搜索樹可以提高查找的效率,但是如果數(shù)據(jù)本身有序,搜索樹將退化成單支樹,查找時相當于順序表查找,效率低下,如下圖: 為了解決上面的問題,來自俄羅斯的兩位天才數(shù)學(xué)家G.M.Adelson-Velskii和E.M.Landis在1962年發(fā)明了一種方

    2024年01月19日
    瀏覽(19)
  • 【數(shù)據(jù)結(jié)構(gòu)】AVL樹/紅黑樹

    【數(shù)據(jù)結(jié)構(gòu)】AVL樹/紅黑樹

    目錄 1.AVL樹(高度平衡二叉搜索樹) 10.1.基本概念 10.2.實現(xiàn) 10.2.1.AVL樹節(jié)點的定義 10.2.2.AVL樹的插入 10.2.3.AVL樹的旋轉(zhuǎn) 1.新節(jié)點插入較高左子樹的左側(cè)---左左:右單旋 2.新節(jié)點插入較高右子樹的右側(cè)---右右:左單旋 3.新節(jié)點插入較高左子樹的右側(cè)---左右:先左單旋再右單旋(左

    2024年02月15日
    瀏覽(22)
  • 【1++的數(shù)據(jù)結(jié)構(gòu)】之AVL樹

    【1++的數(shù)據(jù)結(jié)構(gòu)】之AVL樹

    ??作者主頁:進擊的1++ ?? 專欄鏈接:【1++的數(shù)據(jù)結(jié)構(gòu)】 在說AVL樹之前我們先來說說為什么會出現(xiàn)AVL樹。在前面的文章中我們講過二叉搜索樹,雖然查找,插入效率比較高,但其有個缺陷:在某些情況下其可能會成為一顆單支樹或其他高度較高的樹,這時我們的效率就比較

    2024年02月11日
    瀏覽(19)
  • 數(shù)據(jù)結(jié)構(gòu)與算法——18.avl樹

    數(shù)據(jù)結(jié)構(gòu)與算法——18.avl樹

    這篇文章我們來看一下avl樹 目錄 1.概述 2.AVL樹的實現(xiàn) 我們前面講了二叉搜索樹,它是有一個key值,然后比父節(jié)點key值大的在左邊,小的在右邊。這樣設(shè)計是為了便于查找。但是有一種極端的情況,就是所有的結(jié)點都在一邊,那查找的時間復(fù)雜度和在鏈表的查找時間復(fù)雜度就

    2024年02月07日
    瀏覽(20)
  • 數(shù)據(jù)結(jié)構(gòu):AVL樹講解(C++)

    數(shù)據(jù)結(jié)構(gòu):AVL樹講解(C++)

    普通二叉搜索樹: 二叉搜索樹 二叉搜索樹雖可以縮短查找的效率,但如果 數(shù)據(jù)有序或接近有序普通的二叉搜索樹將退化為單支樹 ,查找元素相當于在順序表中搜索元素,效率低下。因此,兩位俄羅斯的數(shù)學(xué)家G.M.Adelson-Velskii和E.M.Landis在1962年發(fā)明了一種解決上述問題的方法

    2024年02月04日
    瀏覽(20)
  • 【數(shù)據(jù)結(jié)構(gòu)】—AVL樹(C++實現(xiàn))

    【數(shù)據(jù)結(jié)構(gòu)】—AVL樹(C++實現(xiàn))

    ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ????????????? ?? ??慕斯主頁 : 修仙—別有洞天 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??? 本文前置知識: ?搜索二叉樹 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ????????????????? ?? 今日夜電波

    2024年02月05日
    瀏覽(18)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包