算法導論--二叉樹

搜索樹這個數據結果支持很多動態的操作:搜索、最小值啦、最大值,插入和刪除,當然也可以作爲詞典以及優先級隊列。

啥是二叉搜索樹

這裏寫圖片描述

上圖便是二叉搜索樹,一個父節點最大分兩個叉,並且左孩子子樹的所有節點小於等於父節點,右孩子子樹的所有節點大於等於父節點。

這樣就可以通過訪問根節點順序的不同遞歸遍歷這樣的二叉搜索樹,這就是我們所熟知的:前序遍歷,中序遍歷,後序遍歷。
這裏寫圖片描述
上圖僞代碼是中序遍歷,其實中序遍歷二叉搜索樹,就是按從小到大的順序輸出了各個元素,時間複雜是O(n),爲什麼呢,走直覺啊,其實證明也不難啦,自己去看看書裏面人家公式是怎麼推得就明白了。

訪問二叉搜索樹

我們經常需要搜索一個二叉搜索樹。比如找到樹種的最小值、最大值什麼的,這裏介紹一下這些操作是怎麼用O(h)的時間來進行這些操作的,其中h是樹的高度。
搜索:
用一個key值去查找中這個key值得元素。給定一個根節點的指針和一個Key k, TREE-SEARCH返回key=k的節點,如果不存在,返回NULL。
這裏寫圖片描述
很容易理解,這裏不再解釋了。下面給一個非遞歸的算法
這裏寫圖片描述

求最小值:
這裏寫圖片描述
就是一直訪問左子樹,直到空,訪問最大值同理。

Successor 和 Predeccessor
給定一個節點,有時候我們需要找到它的Successor(其實就是比這個節點key值大的節點裏的最小值),原話是這樣的:If all keys are distinct, the successor of a node x is the node with the smallest key greater than x:key。以下的程序返回node x的successor,如果x在樹中有最大的key,則返回NULL。
僞代碼如下:
這裏寫圖片描述
第1-2行:
如果x的右孩子不是空,則返回右子樹的最小節點。
第3行:令y = x的父節點
第4-6行:不太好講,跑個例子就明白了
這裏時間複雜度是O(h),很好理解,不再證明。

插入和刪除節點

有一個點比較重要:就是再插入節點或者刪除節點之後,還要保持二叉搜索的樹的性質。
插入元素的僞代碼如下:
這裏寫圖片描述
第1-2行:初始化操作,令x指向根節點,y爲空。
第4-7行:這個過程保存了一個指針y來指向x的父節點。這個while循環導致兩個指針x和y從根走到葉子節點,直到x變成nil(空)。
第8-13行:這是一個將z插入到制定位置的過程。首先設置z的父節點是y。如果y==nil,說明這棵樹本來是一個空樹,設置T.root = z.然後根據z的key值和y的key值大小的比較,來決定z應該是y的哪個孩子,左孩子還是右孩子。

刪除節點z的策略有三種情況。
第一種情況:如果z沒有孩子,我們直接修改它的父節點指向它的指針爲空即可。
第二種情況:如果z只有一個孩子,將z的父節點指向它的指針指向z的孩子即可
第三種情況:如果z有兩個孩子,我們找到z的successor y,y肯定是z的右子樹。這時候z原來的右子樹成爲y的右子樹,z的左子樹變成y的左子樹。

刪除節點z需要兩個參數爲T和z。

  1. 如果z沒有左孩子,我們將z替換成它的右孩子,無論它的右孩子是否爲空。
  2. 如果z只有一個孩子,並且是左孩子,我們將z替換成它的左孩子
  3. 如果z有兩個孩子,我們找到z的successor y,即是z的右子樹種的一個元素並且沒有左孩子。
  4. 如果y是z的右孩子,我們用y替換掉z,什麼都不用管。
    下圖a,b,c,d分別對應四種情況
    這裏寫圖片描述

僞代碼描述如下:首先先定義一個TRANSPLANT方法:
這裏寫圖片描述
這個方法其實就是將v和u替換在樹中的位置,然後將u丟棄了。
然後是刪除節點的僞代碼:
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章