完整**
二叉搜尋樹是這樣一種二叉樹,對於乙個結點x, 如果它的左子樹的結點值都小於x,它的右子樹的結點值都大於x。並且他的左子樹和右子樹也滿足此特性的二叉樹。二叉搜尋樹的中序遍歷可得到資料的有序序列。
bst結點的前驅是指該結點的前乙個結點,即指向該結點的結點。
bst結點的後繼是指該結點的右子樹中值最接近於該結點值的結點,未必是後乙個結點。
二叉搜尋樹插入結點的過程如下:
1. 如果二叉樹是空樹,建立根結點。
2. 當前值與根結點的值比較,如果當前值小於根結點值,那麼往左子樹,如果當前值大於根結點值,則往右子樹。
3. 重複步驟2,直到到達葉結點。
4. 根據比較大小結果,建立左或右結點,並賦值。
我們以乙個整數序列15, 6, 9, 7, 2, 3, 17, 20, 4, 13, 18來說明整個過程,建立如下圖所示的二叉搜尋樹
我們插入結點值為19的過程如下所示:
1. 首先19與15比較,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 解釋 輸入為 ...