大話數據結構學習筆記 - 查找之二叉排序樹(Binary Sort Tree
)及其C
實現
二叉排序樹
二叉排序樹(Binary Sort Tree
):又稱爲 二叉查找樹, 它或者是一個空樹,或者是具有下列性質的二叉樹
- 若它的左子樹不空,則左子樹上所有結點的值均小於它的根結點的值
- 若它的右子樹不空,則右子樹上所有結點的值均大於它的根結點的值
- 它的左、右子樹也分別爲二叉排序樹
二叉排序樹主要是爲了提高查找和插入刪除關鍵字的速度
二叉樹結構
/* 二叉樹的二叉鏈表結點結構定義 */
typedef struct BiTNode /* 結點結構 */
{
int data; /* 結點數據 */
struct BiTNode *lchild, *rchild; /* 左右孩子指針 */
}BiTNode, *BiTree;
查找
/*
* 遞歸查找二叉排序樹 T 中是否存在 key, 指針 f 指向 T 的雙親, 其初始調用值是 NULL. 若查找成功, 則指針 p 指向該數據元素結點, 並返回 TRUE
* 否則 指針 p 指向查找路徑上訪問的最後一個結點並返回 FALSE
*
*/
Status SearchBST(BiTree T, int key, BiTNode *f, BiTNode **p)
{
if(!T) /* 查找不成功 */
{
*p = f;
return FALSE;
}
else if(key == T->data) /* 查找成功 */
{
*p = T;
return TRUE;
}
else if(key < T->data)
return SearchBST(T->lchild, key, T, p); /* 在左子樹中繼續查找 */
else
return SearchBST(T->rchild, key, T, p); /* 在右子樹中繼續查找 */
}
插入
/*
* 當二叉排序樹 T 中不存在關鍵字等於 key 的數據元素時, 插入 key 並返回 TRUE, 否則返回 FALSE
*/
Status InsertBST(BiTree *T, int key)
{
BiTNode *p, *s;
if(!SearchBST(*T, key, NULL, &p)) /* 查找不成功 */
{
s = CreateBiTNode(key);
if(!p)
*T = s; /* 插入 s 爲新的根節點 */
else if(key < p->data)
p->lchild = s; /* 插入 s 爲左孩子 */
else
p->rchild = s; /* 插入 s 爲右孩子 */
return TRUE;
}
return FALSE; /* 樹中已有關鍵字相同的結點, 不再插入 */
}
刪除
/*
* 從二叉排序樹中刪除節點 p, 並重接它的左或右子樹
*/
Status Delete(BiTNode **p)
{
BiTNode *q, *s;
if((*p)->lchild == NULL) /* 若右子樹爲空,則只需重接它的左子樹 */
{
q = *p;
*p = (*p)->rchild;
free(q);
}
else if((*p)->rchild == NULL) /* 若左子樹爲空,則只需重接它的右子樹 */
{
q = *p;
*p = (*p)->lchild;
free(q);
}
else /* 左右子樹均不空 */
{
q = *p;
s = (*p)->lchild; /* s 爲其左子樹 */
while(s->rchild) /* 轉左,尋找其左子樹最右結點, 即尋找待刪結點的前驅 */
{
q = s;
s = s->rchild;
}
(*p)->data = s->data; /* s 指向被刪結點的直接前驅 */
if(q != (*p))
q->rchild = s->lchild; /* 重接 q 的右子樹 */
else
q->lchild = s->lchild; /* 重接 q 的左子樹 */
free(s);
}
return TRUE;
}
/*
* 若二叉排序樹 T 中存在關鍵字等於 key 的數據元素時, 則刪除該數據元素結點, 並返回 TRUE; 否則返回 FALSE.
*/
Status DeleteBST(BiTree *T, int key)
{
if(!(*T)) /* 不存在關鍵字等於 key 的數據元素 */
return FALSE;
else if(key == (*T)->data) /* 找到關鍵字等於 key 的數據元素 */
return Delete(T);
else if(key < (*T)->data)
return DeleteBST(&(*T)->lchild, key);
else
return DeleteBST(&(*T)->rchild, key);
}
複雜度
若二叉排序樹比較平衡,即其深度與完全二叉樹相同,均爲 ,類似於上圖左圖 那麼查找的時間複雜度就爲 , 近似於折半查找。若插入序列以排好序,則最壞情況類似於上圖右圖,時間複雜度爲 , 等同於順序查找。
代碼
結語
如上複雜度分析,二叉排序樹的超照性能取決於二叉排序樹的形狀,但其形狀不確定,取決於輸入序列。如何構建一個平衡的二叉排序樹呢?請看下節文章 平衡二叉樹