題目編號001 二叉查詢樹轉變成排序的雙向鍊錶

2021-07-02 14:37:32 字數 2850 閱讀 9692

這是第一篇文章也是第乙個題目,希望我能堅持下去,突破自己的程式設計功底。

輸入一棵二元查詢樹,將該二元查詢樹轉換成乙個排序的雙向鍊錶。

要求不能建立任何新的結點,只調整指標的指向。

10/ /

6  14

/ / / /

4  8 12 16

轉換成雙向鍊錶

4=6=8=10=12=14=16。

首先我們定義的二元查詢樹 節點的資料結構如下:

struct bstreenode

;2.1 知識點複習:二叉查詢樹是什麼?

2.1.1 樹

樹(tree)是n(n≥0)個結點的有限集。在任意一棵非空樹中:(1)有且僅有乙個特定的被稱為根(root)的結點;(2)當n>1時,其餘結點可分為m(m>0)個互不相交的有限集t1,t2,…,tm,其中每乙個集合本身又是一棵樹,並且稱為根的子樹(subtree)。

結點擁有的子樹數稱為結點的度(degree)。度為0的結點稱為葉子(leaf)或終端結點。度不為0的結點稱為非終端結點或分支結點。

樹的度是樹內各結點的度的最大值。

結點的子樹的根稱為該結點的孩子(child),相應地,該結點稱為孩子的雙親(parent)。

結點的層次(level)是從根結點開始計算起,根為第一層,根的孩子為第二層,依次類推。樹中結點的最大層次稱為樹的深度(depth)或高度。

如果將樹中結點的各子樹看成從左至右是有次序的(即不能互換),則稱該樹為有序樹,否則稱為無序樹。

2.1.2  二叉樹

二叉樹(binary tree)的特點是每個結點至多具有兩棵子樹(即在二叉樹中不存在度大於2的結點),並且子樹之間有左右之分。

二叉樹的性質:

(1)、在二叉樹的第i層上至多有2i-1個結點(i≥1)。

(2)、深度為k的二叉樹至多有2k-1個結點(k≥1)。

(3)、對任何一棵二叉樹,如果其終端結點數為n0,度為2的結點數為n2,則n0=n2+1。

一棵深度為k且有2k-1個結點的二叉樹稱為滿二叉樹。

可以對滿二叉樹的結點進行連續編號,約定編號從根結點起,自上而下,自左至右,則由此可引出完全二叉樹的定義。深度為k且有n個結點的二叉樹,當且僅當其每乙個結點都與深度為k的滿二叉樹中編號從1到n的結點一一對應時,稱之為完全二叉樹。

(4)、具有n個結點的完全二叉樹的深度為不大於log2n的最大整數加1。

(5)、如果對一棵有n個結點的完全二叉樹的結點按層序編號(從第1層到最後一層,每層從左到右),則對任一結點i(1≤i≤n),有

a、如果i=1,則結點i是二叉樹的根,無雙親;如果i>1,則其雙親是結點x(其中x是不大於i/2的最大整數)。

b、如果2i>n,則結點i無左孩子(結點i為葉子結點);否則其左孩子是結點2i。

c、如果2i+1>n,則結點i無右孩子;否則其右孩子是結點2i+1。

二叉樹的鏈式儲存:

鏈式二叉樹中的每個結點至少需要包含三個域,資料域和左、右指標域。

二叉樹的遍歷:

假如以l、d、r分別表示遍歷左子樹、訪問根結點和遍歷右子樹,則可有dlr、drl、lrd、ldr、rld、rdl這六種遍歷二叉樹的方案。若限定先左後右,則只有三種方案,分別稱之為先(根)序遍歷、中(根)序遍歷和後(根)序遍歷,它們以訪問根結點的次序來區分。

2.1.3 二叉查詢樹

二叉查詢樹(binarysearch tree,也叫二叉搜尋樹,或稱二叉排序樹binary sort tree)或者是一棵空樹,或者是具有下列性質的二叉樹:

(1)、若它的左子樹不為空,則左子樹上所有結點的值均小於它的根結點的值;

(2)、若它的右子樹不為空,則右子樹上所有結點的值均大於它的根結點的值;

(3)、它的左、右子樹也分別為二叉查詢樹。

還有乙個性質是二叉查詢樹一定沒有重複的元素

2.1.4 二叉查詢樹的操作

一般操作就是插入與查詢,無非就是根據關鍵字的大小直接找到底層為null的節點處或者是重複了那麼直接返回null(插入)或者返回(查詢)。其中有意思的是二叉查詢樹的刪除節點操作,這裡貼出**分析下:

static bst_p find_node_by_data(bst_p root,data_type data)

} /*if(p==null)

return null;

else */

return p;

}void delete_bst_node(bst_p *root,data_type data)

//2 運用二叉查詢樹的刪除方法

if(!p->lchild) else if(!p->rchild) else

p->data = s->data;

if(p!=q)

q->rchild = s->lchild;

else

q->lchild = s->lchild;

free(s); }

//注意因為這種刪除的方法並沒有改變原來那個要刪除的節點在整個二叉樹的結構,所以不用怕會動root

}

刪除的原理我總結了是根據保持這顆排序二叉樹在刪除節點之前和之後都要保持中序遍歷序列的不變就行了。而在中序遍歷訪問的時候任何乙個節點他的前驅一定是它左子樹的最右的葉子節點或者是最右的度為1的節點。那麼,可以把這個最右節點的值直接拷貝到要刪除的節點,同時處理下這個最右節點的左子樹,最後釋放這個最右節點就完了。這就是void delete_bst_node(bst_p *root,data_type data)函式的else裡面的**的思想。

2.2 如何做題?

把二叉查詢樹轉變成排序的雙向鍊錶

問題 給乙個二叉查詢樹,把它轉化成排序的雙向鍊錶,要求是不能使用額外的空間 常數空間是允許的 例如 該二叉查詢樹的雙向鍊錶結構是 1 3 4 6 7 8 10 13 14 分析 二叉查詢樹具有非常鮮明的遞迴結構,因此,在解決這道問題時,我們無可避免的會想到用遞迴。關鍵是如何遞迴呢?因為乙個節點總是有...

二叉排序樹轉變成排序的雙向鍊錶

輸入一棵二叉查詢樹,將該二叉查詢樹轉換成乙個排序的雙向鍊錶。要求不能建立任何新的結點,只調整指標的指向。舉例 10 6 14 4 8 12 16 轉換成雙向鍊錶 4 6 8 10 12 14 16 題目要求不能建立任何新的結點,只需要調整指標的指向,那麼就意味著可直接利用二叉樹的結點,通過變更結點的...

二元查詢樹轉變成排序的雙向鍊錶

描述 輸入一顆二元查詢樹,將二元查詢樹轉換成乙個排序的雙向鍊錶。要求不能建立人新建立的結點,只調整指標的指向。我的思路 利用遞迴思想進行解答。1.分解,將結點p分解成左子樹和右自樹兩個部分。2.解決子問題,左子樹變成乙個雙向鍊錶,右子樹變成乙個雙向鍊錶。3.合併,將結點p的left 連線到左子樹中最...