資料結構之 二叉查詢樹(C語言實現)
阿新 • • 發佈:2018-12-25
資料結構之 二叉查詢樹
1. 二叉查詢樹的定義
二叉查詢樹(binary search tree)是一棵二叉樹,或稱為二叉搜尋樹,可能為空;一棵非空的二叉查詢樹滿足一下特徵:
- 每個元素有一個關鍵字,並且任意兩個元素的關鍵字都不同;因此,所有的關鍵字都是唯一的。
- 在根節點的左子樹中,元素的關鍵字(如果存在)都是小於根節點的關鍵字。
- 在根節點的右子樹中,元素的關鍵字(如果存在)都是大於根節點的關鍵字。
- 根節點的左、右子樹也都是二叉查詢樹。
2. 二叉查詢樹的操作和實現
二叉查詢樹是基於一個二叉樹滿足以上特徵所實現的,因此關於二叉樹的操作實現的博文:二叉樹(C語言實現)
2.1 二叉查詢樹的抽象資料型別
typedef int myType;
typedef struct treeNode
{
myType element; //值域元素
struct treeNode *lchild; //左子樹
struct treeNode *rchild; //右子樹
}searchTree;
2.1 查詢
遞迴查詢關鍵字為data的元素,時間複雜度為O(h),h是樹的高度
searchTree *find(myType data, searchTree *T)
{
if(T == NULL )
return NULL;
if(data < T->element) //如果小於根節點值則去左孩子查詢
return find(data, T->lchild);
else if(data > T->element)//如果大於根節點值則去左孩子查詢
return find(data, T->rchild);
else
return T;
}
2.2 查詢最小值(遞迴實現)
根據二叉查詢樹的性質,遍歷左子樹。
searchTree *findMin(searchTree *T)
{
if(T == NULL)
return NULL;
else if(T->lchild == NULL)
return T;
else
return findMin(T->lchild);
}
2.3 查詢最大值(非遞迴實現)
根據二叉查詢樹的性質,遍歷右子樹。
searchTree *findMax(searchTree *T)
{
if(T != NULL)
while(T->rchild != NULL)
T = T->rchild;
return T;
}
2.4 插入
如果data不存在,則插入,根據二叉查詢樹的性質,如果大於根節點元素,進入右子樹,如果小於根節點元素則進入左子樹。
searchTree *insert(myType data, searchTree *T)
{
if(T == NULL) {
T = (searchTree *)malloc(sizeof(struct treeNode));
T->element = data;
T->lchild = NULL;
T->rchild = NULL;
} else if (data < T->element) {
lchild = insert(data, T->lchild);
} else if (data > T->element) {
rchild = insert(data, T->rchild);
}
return T;
}
2.5 刪除
刪除操作有三種情況
- T是葉子節點。直接釋放該節點的空間,如果是根節點,則直接賦值為NULL。
- T有一棵非空子樹。如果是根節點,則T的唯一子樹成為根節點,如果非根節點,則使其父節點指標繞過該節點指向其唯一子節點,釋放空間。
- T有兩棵非空子樹。一般策略是將該節點的元素替換成它的左子樹的最大元素或右子樹的最小元素(程式碼中採用的是後者,即用右子樹的最小元素替換被刪除的節點),然後在刪除被替換的元素。
searchTree *remove(myType data, searchTree *T)
{
searchTree *tmpNode;
if(T == NULL) {
printf("NOT FOUNT\n");
} else if (data < T->element) {
T->lchild = remove(data, T->lchild);
} else if (data > T->element) {
T->rchild = remove(data, T->rchild);
//找到該元素,開始刪除
} else if (T->lchild && T->rchild){
//有兩個子樹的情況
tmpNode = findMin(T->rchild);
T->element = tmpNode->element;
T->rchild = remove(T->element, T->rchild);
} else {
//有一個或沒有子樹的情況
tmpNode = T;
if(T->lchild == NULL)
T = T->rchild; //繞過被刪除的節點
else if(T->rchild == NULL)
T = T->lchild;
free(tmpNode);
}
return T;
}
//以上程式碼在刪除有兩個子樹的情況效率不高,因為查詢和刪除右子樹中最小的節點遍歷了兩趟。
以上關於二叉查詢樹的操作時間複雜度均為O(