二叉查找樹
- 特點
- 左子樹所有值都小於根值
- 右子樹所有值都大於根值
- 理論上不能有相同
- 操作
- 查找
- 插入
- 刪除
查找
- 判斷與根值是否相等,相等則完成
- 否則,判斷與根值大小關係
- 若小於根值,則:當目標值存在時,值一定左子樹裏
- 若大於根值,則:當目標值存在時,值一定右子樹裏
- 當搜索到空時,則不存在
BST search( keytype k, BST F ) // k:目標值;F:當前查找子樹的根節點
{
p = F ;
if ( p == NULL ) return Null ;
else if (k == p->data.key) return p; // 相等,查找成功
else if (k < p->data.key) // 目標值小於根值
return search (k, p->lchild); // 進入左子樹
else if (k > p->data.key) // 目標值大於根值
return search (k, p->rchild); // 進入右子樹
}
插入
- 核心點:值一定在樹的最底端插入
- 因此,從根節點往下搜索合適的插入位置時,一定要到一個***“空位”(NULL)才能新建節點***
- 依據性質:左子樹的所有值一定小於根值,右子樹的所有值一定小於根值
- 在任意一個時刻,小於根值則插入左子樹,大於根值則插入右子樹
- 當選擇的子樹爲空時則插入(新建節點)
- 程序中的這一步:先假設不爲空,進入這一節點(NULL),再在進入迭代時
Void Insert (Records R, BST &F)
{
if ( F == NULL ) { // 已經查找到底層,可以插入新節點
F = new CellType ; // 新建節點
F->data = R ; // 存值
F->lchild = NULL ; // 預設左右子樹都爲NULL
F->rchild = NULL ;
}
else if ( R.key < F->data.key ) // 插入的值小於根值,往左子樹插入
Insert ( R , F->lchild )
else if ( R.key >= F->data.key ) // 插入的值大於根值,往右子樹插入
Insert ( R , F->rchild )
}
刪除
刪除三類結點:
- 被刪除的結點是葉子結點
- 被刪除的結點只有一顆非空的左子樹或右子樹
- 被刪除的結點有兩棵非空的子樹
Void Delete ( keytype k ,BST &F )
{
if ( F != NULL )
if ( k < F->data.key ) Delete( k, f->lchild ) ; // 目標值比根值小,進入左兒子
else if ( k > F->data.key ) Delete( k, f->rchild ); // 目標值比根值大,進入右兒子
else // 找到該元素,開始刪除
if ( F->rchild == NULL ) F = F->lchild ; // 一邊兒子爲空,則用另一邊兒子代替
else if ( F->lchild == NULL ) F = F->rchild ;
else F->data = DeleteMin(F->rchild) // 兩邊都有兒子,進行DeleteMin操作
}
// 取右子樹中最小的(即最左兒子),DeleteMin以此爲例
// 同理,也可以取左子樹最大
Records DeleteMin( F ) // F:右子樹的根
{
records tmp ;
BST p ;
if ( F->lchild == NULL ) { // 已經找到最左兒子
p = F ;
tmp = F->data ; // 暫存節點的信息
F = F->rchild ; // 該節點刪除,右兒子補上(無左兒子 and 可能是空)
Delete p ; // 刪除p(當前F)節點
return tmp ; // 返回data給上個函數要刪除的點,即將右子樹的最左兒子的移到刪除點的位置
}
else
return ( DeleteMin( F->lchild ) ; // 未找到最左,繼續往左找
}