二叉搜尋樹 Binary Search Tree

2021-07-30 18:43:25 字數 3798 閱讀 1727

完整**

二叉搜尋樹是這樣一種二叉樹,對於乙個結點x, 如果它的左子樹的結點值都小於x,它的右子樹的結點值都大於x。並且他的左子樹和右子樹也滿足此特性的二叉樹。二叉搜尋樹的中序遍歷可得到資料的有序序列。

bst結點的前驅是指該結點的前乙個結點,即指向該結點的結點。

bst結點的後繼是指該結點的右子樹中值最接近於該結點值的結點,未必是後乙個結點。

二叉搜尋樹插入結點的過程如下:

1. 如果二叉樹是空樹,建立根結點。

2. 當前值與根結點的值比較,如果當前值小於根結點值,那麼往左子樹,如果當前值大於根結點值,則往右子樹。

3. 重複步驟2,直到到達葉結點。

4. 根據比較大小結果,建立左或右結點,並賦值。

我們以乙個整數序列15, 6, 9, 7, 2, 3, 17, 20, 4, 13, 18來說明整個過程,建立如下圖所示的二叉搜尋樹

我們插入結點值為19的過程如下所示:

1. 首先1915比較,19 > 15 所以走右子樹

2. 右子結點值為17,19 > 17 所以走右子樹

3. 右子結點值為2019 < 20 所以走左子樹

4. 左子結點值為1819 > 18 所以走右子樹

5.18為葉結點,所以將19插入到18的右子結點

插入過程如下圖所示:

bst的結構如下所示:

typedef

struct bstreenode bstreenode;

其中elem,表示當前結點的值,leftchild, rightchild分別指向該結點的左子結點和右子結點。

中序遍歷,就是二叉樹的中序遍歷,先遍歷左子樹,再遍歷根結點,再遍歷右子樹,以這樣的遞迴方式進行。遍歷**如下:

void inorder(struct bstreenode* bstree)

bst的查詢類似於二分查詢,如果結點的值等於當前結點的值,返回該值,如果結點值小於當前值,繼續查詢左子樹,如果結點的值大於當前的值,繼續查詢右子樹。**如下所示:

bool find(struct bstreenode* bstree, int elem)

return p != null;

}

bst的查詢和遍歷都比較容易,但是bst的刪除,則有一點點複雜。可以分為以下幾種情況

1. 刪除葉結點

2. 刪除只有左子樹的結點

3. 刪除只有右子樹的結點

4. 刪除包含左右子樹的結點

葉結點的刪除很容易,直接刪除該結點即可,但是需要注意的一點是,我們需要找到該結點的前驅結點,才能將對應的結點指標的記憶體正確釋放。

根據二叉樹的性質,可以知道,左子結點的值都是小於該結點的值,所以要刪除該結點,那麼該結點的前驅結點的對應結點,即指向該結點的左子樹。

根據二叉樹的性質,可以知道,右子結點的值都是大於該結點的值,所以要刪除該結點,那麼該結點的前驅結點的對應結點,即指向該結點的右子樹。

要刪除該型別的結點,首先要找到該結點的後繼,根據二叉樹的性質可以知道,該結點的後繼位於該結點的右子結點的左子樹上,且其後繼必沒有左子樹(因為如果還有左子樹,說明還有更小的值更接近該結點的值),那麼該結點的右子結點的左子樹指標應指向其後繼的右子樹。

比如說刪除結點值17的結果如下:

完整**示例如下所示:

#include 

#include

#include

#define safedelete(ptr) }

typedef

struct bstreenode bstreenode;

void insertnode(struct bstreenode* bstree, int elem, bool root = false)

else

}else}}

}return ;

}bool find(struct bstreenode* bstree, int elem)

return p != null;

}void delete(struct bstreenode* bstree, int elem)

if(p)

//如果p左子樹不為空,右子樹為空

else

if(p->leftchild != null && p->rightchild == null)

//如果p右子樹不為空,左子樹為空

else

if(p->leftchild == null && p->rightchild != null)

//如果p左、右子樹均不為空

else}}

return ;

}void inorder(struct bstreenode* bstree)

void destroytree(struct bstreenode* bstree)

int main(int argc, const

char * argv)

; struct bstreenode* bstree = (struct bstreenode*)malloc(sizeof(struct bstreenode));

for(int i = 0 ; i != sizeof(arr) / sizeof(int); ++i)

insertnode(bstree, arr[i], i == 0);

printf("原二叉搜尋樹中序:");

inorder(bstree);

printf("\n");

printf("查詢結點值為13的結點:");

printf("%s\n", find(bstree, 13) ? "find it." : "not found");

printf("查詢結點值為30的結點");

printf("%s\n", find(bstree, 30) ? "find it." : "not found");

insertnode(bstree, 16);

insertnode(bstree, 19);

printf("插入16、 19兩個結點:");

inorder(bstree);

printf("\n");

delete(bstree, 15);

delete(bstree, 19);

printf("刪除15、 19兩個結點:");

inorder(bstree);

printf("\n");

//銷毀二叉樹

destroytree(bstree);

return

0;}

最終的執行結果如下所示:

如有錯誤,望批評指正。

二叉搜尋樹 二叉搜尋樹

題目 二叉搜尋樹 time limit 2000 1000 ms j a others memory limit 32768 32768 k j a others total submission s 6945 accepted submission s 3077 problem descripti...

二叉搜尋樹 修剪二叉搜尋樹

第一反應是重構,看來別人的解答發現,其實不用重構那麼複雜。treenode trimbst treenode root,int low,int high if root val high 下一層處理完左子樹的結果賦給root left,處理完右子樹的結果賦給root right。root left ...

樹 二叉樹 二叉搜尋樹

給定乙個二叉樹,判斷其是否是乙個有效的二叉搜尋樹。假設乙個二叉搜尋樹具有如下特徵 節點的左子樹只包含小於當前節點的數。節點的右子樹只包含大於當前節點的數。所有左子樹和右子樹自身必須也是二叉搜尋樹。示例 1 輸入 2 13輸出 true 示例 2 輸入 5 14 3 6輸出 false 解釋 輸入為 ...