二叉排序樹或者是一棵空樹,或者是具備下列性質的二叉樹
1)若左子樹不空,則左子樹上全部結點的值均小於或等於它的根結點的值;
2)若右子樹不空,則右子樹上全部結點的值均小於或等於它的根結點的值;
3)左、右子樹也分別爲二叉排序樹;
查找步驟:
若根結點的關鍵字值等於查找的關鍵字,成功;
不然,若小於根結點的關鍵字值,遞歸查左子樹。
若大於根結點的關鍵字值,遞歸查右子樹。
若子樹爲空,查找不成功。
簡介:
二叉排序樹一般採用二叉鏈表做爲存儲結構。中序遍歷二叉排序樹可獲得一個依據關鍵字的有序
序列,一個無序序列能夠經過構造一棵二叉排序樹變成一個有序序列,構造樹的過程便是對無序序列
進行排序的過程。每次插入的新的結點都是二叉排序樹上新的葉子結點,在進行插入操做,沒必要移動
其餘結點,只需改動某個結點的指針,由空變爲非空便可。搜索、插入、刪除的時間複雜度等於樹高
,指望O(logn),最壞就是O(n);
定義結構:
/* 二叉樹的二叉鏈表結點結構定義 */
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, BiTree f,BiTree *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)
{
BiTree p,s;
if(!SearchBST(*T, key, NULL, &p)) /* 查找不成功 */
{
s = (BiTree)malloc(sizeof(BiTNode));
s->data = key;
s->lchild = s->rchild = NULL;
if(!p)
{
*T = s; //插入s爲新的根結點
}
else if(key < p->data)
p->lchild = s; //插入s爲左孩子
else
p->rchild = s; //插入s爲右孩子
return TURE;
}
else
return FALSE; /* 樹中已有關鍵字相同的結點,再也不插入 */
}
二叉排序樹的刪除算法
在二叉排序樹中刪去一個結點,分三種狀況:
1.若 *p結點爲葉子結點,即PL(左子樹)和PR(右子樹)均爲空樹。因爲刪去葉子結點
不破壞整棵樹的結構,則只需修改其雙親結點的指針便可。
2.若 *p結點只有左子樹PL或右子樹PR,此時只要令PL或PR直接成爲其雙親結點*f的
左子樹(當*p是左子樹)或右子樹(當*p是右子樹)便可,作此修改也不破壞二叉排序
樹的特性。
3.若*p結點的左子樹和右子樹均不空。在刪去*P以後,爲保持其餘元素之間的相對位置
不變,可按中序遍歷保持有序進行調整。比較好的作法是,找到*p的直接前驅(或後繼
)*s,用*s來替換結點*p,而後再刪除結點*s;
/* 若二叉排序樹T中存在關鍵字等於key的數據元素,則刪除該數據元素結點 */
/* 並返回TRUE;不然返回FALSE */
Status DeleteBSD(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);
}
}
/* 從二叉排序樹中刪除結點p,並重接它的左或右子樹 */
Status Delete(BiTree *p)
{
BiTree q,s;
if((*p)->rchild == NULL)//右子樹空則只需重接它的左子樹(待刪結點是葉子也走此分支)
{
q = *p;
*p=(*p)->lchild;
free(q);
q= NULL;
}
else if((*p)->lchild == NULL)//只需重接它的右子樹
{
q = *p;
*p = (*p)->rchild;
free(q);
q= NULL;
}
else //左右子樹均不空
{
q = *p;
s = (*p)->lchild;
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);
s = NULL;
}
return TRUE;
}算法