前言
二叉排序樹,又稱爲二叉查找樹,它具有以下特點:
若它的左子樹不空,則左子樹所有結點值均小於它的根結點的值
若它的右子樹不空,則右子樹所有結點值均大於它的根結點的值
它的左,右子樹也分別爲二叉排序樹
可以爲空
前提是二叉樹,然後也採用了遞歸的定義方法
二叉排序樹中序遍歷就一有序表
構造一顆二叉樹,就是把一無序的順序表變爲有序的數集,中序遍歷二叉排序表就是一有序的表,其目的,並不是爲了排序,而是爲了提高查找和刪除關鍵字的速度。
1.關鍵字
二叉排序樹的結構體定義和二叉樹的結構體定義完全一樣
我們存儲的數據都是關鍵字,說白了就是編號,查找的時候也是,因此在本篇中關鍵字是唯一的,不能出現兩個相同的關鍵字。
2.二叉排序樹的查找操作
查找函數,我們定義爲一個可遞歸運行的函數,函數調用時的語句爲:SearchBT(T,key,f,p);參數T爲一個二叉鏈表,key爲查找的關鍵字,f爲指向T的雙親,p爲了得到查找到的結點位置。
代碼如下:
Status SearchBT(BTree T,TElemType key,BTree f,BTree *p)
{
if(!T)//查找不成功
{
*p = f;
return FALSE;
}
else if(key == T->data)//查找成功
{
*p = T;
return TRUE;
}
else if(key < T->data)
{
return SearchBT(T->lchild,key,T,p);
}
else
return SearchBT(T->rchild,key,T,p);
}
2.二叉排序樹的插入操作
只有查得不到的時候,纔會進行插入操作,並且將關鍵字放到樹中合適的位置。
代碼如下:
Status InsertBT(BTree *T,TElemType key)
{
BTree p,s;
if(!SearchBT(*T,key,NULL,&p))//查找失敗
{
s = (BTree)malloc(sizeof(BTNode));
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 TRUE;
}
else
return FALSE;
}
3.二叉排序樹的刪除操作
刪除操作分爲三種情況
1.要刪除的結點只有左子樹,刪除後,將他的左子樹整個移動到結點位置
2.要刪除的結點只有右子樹,刪除後,將他的右子樹整個移動到結點位置
3.要刪除的結點既有左子樹又有右子樹。找到此結點p的有序直接前驅(或直接後驅)s,用s來替換結點p。然後再刪除結點s。
代碼如下
Status Delete(BTree *p)
{
BTree q,s;
if((*p)->rchild == NULL)//右子樹空只需連接它的左子樹
{
q = *p; *p = (*p)->lchild; free(q);
}
else if((*p)->lchild == NULL)//左子樹空只需連接它的右子樹
{
q = *p; *p = (*p)->rchild; free(q);
}
else//左右子樹均不空
{
q = *p; s = (*p)->lchild;
while(s->rchild)//轉左,然後向右到盡頭
{
q = s;s = s->rchild;
}
(*p)->data = s->data;
if(q != *p)
q->rchild = s->lchild;//重接q的右子樹
else
q->lchild = s->lchild;//重接q的左子樹
free(s);
}
return TRUE;
}
4.總結
二叉排序樹其實就是一種把無序的順序表變爲一個有序表,二叉排序樹中序遍歷就是有序表。
查找利用了類似二分查找的原理
完整代碼
以數組
a[10] = {62,88,58,47,35,73,51,99,37,93};
爲例:
#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
typedef int Status;
typedef int TElemType;
typedef struct BTNode
{
TElemType data;
struct BTNode *lchild,*rchild;
}BTNode,*BTree;
Status SearchBT(BTree T,TElemType key,BTree f,BTree *p);//查找算法
Status InsertBT(BTree *T,TElemType key);//插入算法
Status Delete(BTree *p);//刪除數據算法
Status DeleteBT(BTree *T,TElemType key);//刪除算法
void InOrderTraverse(BTree T);//中序遍歷二叉樹
int main()
{
int i,x,n,m;
BTree p = NULL;
BTree T = NULL;
int a[10] = {62,88,58,47,35,73,51,99,37,93};
for(i=0;i<10;i++)
{
InsertBT(&T,a[i]);
}
while(1)
{
printf("1.中序遍歷 2.刪除算法 3.添加算法 4.查找算法\n");
scanf("%d",&n);
switch(n)
{
case 1:
printf("中序遍歷二叉樹\n");
InOrderTraverse(T);
printf("\n");
break;
case 2:
printf("輸入要刪除的數\n");
scanf("%d",&x);
m = DeleteBT(&T,x);
if(m==TRUE)
{
InOrderTraverse(T);
printf("\n");
}
else
printf("刪除失敗\n");
break;
case 3:
printf("輸入要添加的數\n");
scanf("%d",&x);
m = InsertBT(&T,x);
if(m==TRUE)
{
InOrderTraverse(T);
printf("\n");
}
else
printf("添加失敗\n");
break;
case 4:
printf("輸入要查找的數\n");
scanf("%d",&x);
m = SearchBT(T,x,NULL,&p);
if(m==TRUE)
{
printf("查得:%d\n",x);
}
else
printf("查找失敗\n");
break;
}
}
}
Status SearchBT(BTree T,TElemType key,BTree f,BTree *p)
{
if(!T)//查找不成功
{
*p = f;
return FALSE;
}
else if(key == T->data)//查找成功
{
*p = T;
return TRUE;
}
else if(key < T->data)
{
return SearchBT(T->lchild,key,T,p);
}
else
return SearchBT(T->rchild,key,T,p);
}
Status InsertBT(BTree *T,TElemType key)
{
BTree p,s;
if(!SearchBT(*T,key,NULL,&p))//查找失敗
{
s = (BTree)malloc(sizeof(BTNode));
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 TRUE;
}
else
return FALSE;
}
Status Delete(BTree *p)
{
BTree q,s;
if((*p)->rchild == NULL)//右子樹空只需連接它的左子樹
{
q = *p; *p = (*p)->lchild; free(q);
}
else if((*p)->lchild == NULL)//左子樹空只需連接它的右子樹
{
q = *p; *p = (*p)->rchild; free(q);
}
else//左右子樹均不空
{
q = *p; s = (*p)->lchild;
while(s->rchild)//轉左,然後向右到盡頭
{
q = s;s = s->rchild;
}
(*p)->data = s->data;
if(q != *p)
q->rchild = s->lchild;
else
q->lchild = s->lchild;
free(s);
}
return TRUE;
}
Status DeleteBT(BTree *T,TElemType key)
{
if(!*T)//要刪除的數不存在
return FALSE;
else
{
if(key == (*T)->data)
return Delete(T);
else if(key < (*T)->data)
return DeleteBT(&(*T)->lchild,key);
else
return DeleteBT(&(*T)->rchild,key);
}
}
void InOrderTraverse(BTree T)
{
if(T == NULL)
return;
InOrderTraverse(T->lchild);
printf("%d ",T->data);
InOrderTraverse(T->rchild);
}
運行結果
後記
二叉排序樹其實就是爲了動態查找而產生的
還記得動態查找是什麼嗎:
動態查找在查找過程中插入不存在的元素,刪除已存在的元素。
今天的內容就是二叉排序樹的基本操作及其內容,喜歡我的多多支持哦~