二叉搜索树(二叉排序树、二叉查找树)
1.定义
二叉搜索树(Binary Search Tree):用于排序和查找都很有用的特殊二叉树。在以下操作中,规定各结点彼此键值不同。
2.性质
(1)非空左子树的所有键值小于其根节点的键值;
(2)非空右子树的所有键值大于其根节点的键值;
(3)左、右子树都是二叉搜索树;
3.抽象数据类型
类型名称:二叉搜索树(Binary Search Tree)
数据对象集:一个有穷的结点集合。这个集合可以为空,若不为空,则由根节点和其左、右二叉子树组成。
操作集:对于所有BT属于BinTree,有
(1)bool IsEmpty(BinTree BT)
:若BT为空返回true;否则返回false
(2)void Traversal(BinTree BT)
:二叉树的遍历
(3)BinTree CreatBinTree()
:创建一个二叉树
(4)Position Find(BinTree BST,ElementType X)
:从二叉搜索树BST中查找元素X,返回其所在结点的地址;
(5)Position FindMin(BinTree BST)
:从二叉搜索树中查找并返回最小元素所在结点的地址
(6)Position FindMax(BinTree BST)
:从二叉搜索树中查找并返回最大元素所在结点的地址
4.C语言实现(重点为插入与删除)
//二叉搜索树
#include<stdio.h>
#include<stdlib.h>
#define NoInfo 0
#define ERROR NULL
typedef int ElementType;
typedef struct TNode * Position_TNode;
typedef struct TNode * BinTree; /* 二叉树类型 */
typedef struct Node * PtrToNode;
typedef struct Node * Position_Node;
typedef struct QNode * PtrToQNode;
typedef struct QNode * Queue;
struct TNode{ /* 树结点定义 */
ElementType Data; /* 结点数据 */
BinTree Left; /* 指向左子树 */
BinTree Right; /* 指向右子树 */
};
struct Node { /* 队列中的结点 */
BinTree Data_BinTree;//结点数据为BinTree类型的指针
PtrToNode Next;
};
struct QNode {
Position_Node Front;
Position_Node Rear; /* 队列的头、尾指针 */
};
//bt打印
BinTree DeleteQ( Queue Q );
bool AddQ(Queue Q,BinTree x);
Queue CreateQueue();
bool IsEmpty( Queue Q );
void LevelorderTraversal(BinTree BT);//层序打印
//二叉搜索树创建(插入)即及删除
Position_TNode Find(BinTree BST,ElementType X);//二叉搜索树的查找
Position_TNode FindMax(BinTree BST);//查找二叉搜索树中最大值
Position_TNode FindMin(BinTree BST);//最小值
BinTree Insert(BinTree BST,ElementType X);//二叉搜索树的插入
BinTree Delete(BinTree BST,ElementType X);//二叉搜索树的删除
int main(){
BinTree bst=NULL;
// 30
// 15 41
// 33 50
// 35
// 34
bst=Insert(bst,30);
bst=Insert(bst,15);
bst=Insert(bst,41);
bst=Insert(bst,33);
bst=Insert(bst,50);
bst=Insert(bst,35);
bst=Insert(bst,34);
LevelorderTraversal(bst);
return 0;
}
BinTree DeleteQ( Queue Q )
{
Position_Node FrontCell;
BinTree FrontElem;
if ( IsEmpty(Q) ) {
printf("队列空");
return ERROR;
}
else {
FrontCell = Q->Front;
if ( Q->Front == Q->Rear ) /* 若队列只有一个元素 */
Q->Front = Q->Rear = NULL; /* 删除后队列置为空 */
else
Q->Front = Q->Front->Next;
FrontElem = FrontCell->Data_BinTree;
free( FrontCell ); /* 释放被删除结点空间 */
return FrontElem;
}
}
Queue CreateQueue()
{
Queue Q=(Queue)malloc(sizeof(struct QNode));
Q->Front=Q->Rear=NULL;
return Q;
}
bool IsEmpty( Queue Q )
{
return ( Q->Front == NULL);
}
bool AddQ(Queue Q,BinTree x)
{
Position_Node RearCell=(Position_Node)malloc(sizeof(struct Node));
if(IsEmpty(Q)){
Q->Front=Q->Rear=RearCell;
Q->Rear->Data_BinTree=x;
Q->Rear->Next=NULL;
}
else{
Q->Rear->Next=RearCell;
Q->Rear=RearCell;
Q->Rear->Data_BinTree=x;
Q->Rear->Next=NULL;
}
}
void LevelorderTraversal(BinTree BT){
Queue Q;
Q=CreateQueue();
BinTree T;
AddQ(Q,BT);
while(!IsEmpty(Q)){
T=DeleteQ(Q);
printf(" %d ",T->Data);
if(T->Left) AddQ(Q,T->Left);
if(T->Right) AddQ(Q,T->Right);
}
}
Position_TNode Find(BinTree BST,ElementType X){
while(BST){
if(X>BST->Data){
BST=BST->Right;
}
else if(X<BST->Data){
BST=BST->Left;
}
else break;
}
return BST;
}
//递归实现查找
//Position_TNode Find(BinTree BST,ElementType X)
//{
// if(!BST) return NULL;
// if(X>BST->Data) return Find(BST->Right,X);
// else if(X<BST->Data) return Find(BST->Left,X);
// else return BST;//X==BST->Data
//}
Position_TNode FindMin(BinTree BST){
if(!BST) return NULL;
else if(!BST->Left) return BST;
else return FindMin(BST->Left);
}
Position_TNode FindMax(BinTree BST){
if(!BST) return NULL;
else if(!BST->Right) return BST;
else return FindMax(BST->Right);
}
BinTree Insert(BinTree BST,ElementType X){
BinTree bst;//bst为待插入的结点
BinTree tmp,bst_fatherNode;//tmp为遍历树的指针,bsst_fatherNode为bst的父节点
bst_fatherNode=(BinTree)malloc(sizeof(struct TNode));
bst_fatherNode->Left=bst_fatherNode->Right=NULL;
tmp=(BinTree)malloc(sizeof(struct TNode));
tmp->Left=tmp->Right=NULL;
bst=(BinTree)malloc(sizeof(struct TNode));
bst->Left=bst->Right=NULL;
//初始化各指针
if(!BST){
BST=(BinTree)malloc(sizeof(struct TNode));
BST->Data=X;
BST->Left=BST->Right=NULL;
}//若树为空直接插入头结点
else{
tmp=BST;//由于需返回树,故用 tmp指针 查找 新节点 应插入的位置
while(tmp){//当tmp为NULL说明 tmp位置 为 将要被插入的结点 的位置
if(X<tmp->Data){
bst_fatherNode=tmp;//记录被插入结点的父节点,便于构建二叉树
tmp=tmp->Left;
}
else if(X>tmp->Data){
bst_fatherNode=tmp;
tmp=tmp->Right;
}
}
if(X<bst_fatherNode->Data){
bst->Data=X;
bst_fatherNode->Left=bst;//将父节点的左指针 指向 被插入的结点
bst->Left=bst->Right=NULL;
}
if(X>bst_fatherNode->Data){
bst->Data=X;
bst_fatherNode->Right=bst;
bst->Left=bst->Right=NULL;
}
}
return BST;
}
//递归实现插入
//BinTree Insert(BinTree BST,ElementType X){
// if(!BST){
// BST=(BinTree)malloc(sizeof(struct TNode));
// BST->Data=X;
// BST->Left=BST->Right=NULL;
// }
// else{
// if(X<BST->Data){
// BST->Left=Insert(BST->Left,X);
// }
// else if(X>BST->Data){
// BST->Right=Insert(BST->Right,X);
// }
// //规定了各结点键值不同,故若BST->Data==X则什么都不做
// }
// return BST;
//}
BinTree Delete(BinTree BST,ElementType X){
Position_TNode Tmp;
if( !BST )
printf("要删除的元素未找到");
else
{
if( X < BST->Data )
BST->Left = Delete( BST->Left, X ); /* 从左子树递归删除 */
else if( X > BST->Data )
BST->Right = Delete( BST->Right, X ); /* 从右子树递归删除 */
//类似查找过程
else { /* BST就是要删除的结点 */
// 如果被删除结点有左右两个子结点 用右子树最小元素或左子树最大元素替代
if( BST->Left && BST->Right ) {
/* 从右子树中找最小的元素填充删除结点 */
Tmp = FindMin( BST->Right );
BST->Data = Tmp->Data;
/* 从右子树中删除最小元素 */
BST->Right = Delete( BST->Right, BST->Data );
}
else { /* 被删除结点有一个或无子结点 */
Tmp = BST;
if( !BST->Left ) /* 只有右孩子或无子结点 */
BST = BST->Right;
//当无子结点时,让 被删除结点的父节点 指向 被删除结点 的指针 指向NULL(BST->Left==NULL)
else /* 只有左孩子 */
BST = BST->Left;
free( Tmp );
}
}
}
return BST;//删除中的遍历改变的是BST->Left和BST->Right指针,故BST仍指向根节点
}