二叉排序树的建立、插入、删除和查找
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int key;
struct node *lchild,*rchild;
}BSTNode;
//二叉排序树插入操作递归算法
BSTNode *InsertBST1(BSTNode *T, int key)
{
BSTNode *p, *q = T;
//p为待插入的新结点
p = (BSTNode *)malloc(sizeof(BSTNode));
p->key = key;
p->lchild = p->rchild = NULL;
if(T == NULL) //原树为空
T = p; //新插入的结点为新的根
//原树非空时将新结点p作为q的左孩子或右孩子插入
else
{
if(key == q->key)
return T;
if(key < q->key)
{
if(q->lchild ==NULL)
q->lchild = p;
else
InsertBST1(q->lchild, key);
}
if(key > q->key)
{
if(q->rchild ==NULL)
q->rchild = p;
else
InsertBST1(q->rchild, key);
}
}
return T;
}
////二叉排序树插入操作非递归算法
BSTNode *InsertBST2(BSTNode *T, int key)
{
BSTNode *f, *p = T;
//查找插入位置
while(p)
{
if(key == p->key)
return T;//无须插入
f = p;//记录访问的结点
if(key < p->key)
p = p->lchild;
else
p = p->rchild;
//若key<p->key,则在左子树中查找,否则在右子树中查找
}
//p为待插入的新结点
p = (BSTNode *)malloc(sizeof(BSTNode));
p->key = key;
p->lchild = p->rchild = NULL;
if(T == NULL) //原树为空
T = p; //新插入的结点为新的根
//原树非空时将新结点q作为p的左孩子或右孩子插入
else
{
if(key < f->key)
f->lchild = p;
else f->rchild = p;
}
return T;
}
//二叉排序树删除操作
void DelBST(BSTNode *T,int key)
{
BSTNode *p = T, *f, *q, *s;
while(p)
{
if(p->key == key) break; //找到关键字为key的结点
f=p;//记下关键字key节点的父节点
p=(key < p->key)? p->lchild : p->rchild;//分别在*p的左、右子树中查找
}
if(!p) return;//二叉排序树中无关键字为key的结点
if(p->lchild == NULL && p->rchild == NULL)//p无左子树无右子树
{
if(p == T) T = NULL;//删除的是根节点
else
if(p == f->lchild)
f->lchild = NULL;
else
f->rchild = NULL;
}
else if(p->lchild == NULL && p->rchild != NULL)//p无左子树有右子树
{
if(f->lchild == p)
f->lchild = p->rchild;
else
f->rchild = p->rchild;
}
else if(p->rchild == NULL && p->lchild != NULL)//p有左子树无右子树
{
if (f->lchild == p)
f->lchild = p->lchild;
else
f->rchild = p->lchild;
}
else if(p->lchild != NULL && p->rchild != NULL)//p既有左子树又有右子树
{
q = p;
s = p->lchild;//转左
while(s->rchild)
{//然后向右到尽头
q = s;
s = s->rchild;//s指向被删节点的“前驱”(中序前驱)
}
p->key = s->key;//以p的中序前趋结点s代替p(即把s的数据复制到p中)
if(q != p)
q->rchild = s->lchild;//重接q的右子树
else
q->lchild = s->lchild;//重接q的左子树。
}
}
//创建二叉排序树
BSTNode *CreateBST()
{
BSTNode *T = NULL; //初始时T为空树
int key;
printf("请输入一系列数,以0结尾:");
while(1)
{
scanf("%d", &key);//读入一关键字
if(key == 0)
break;//假设key=0是输入结束标志
else
T = InsertBST1(T, key); //使用递归算法,将key插入二叉排序树T,改为 T = InsertBST2(T, key);为非递归插入算法
}
return T; //返回建立的二叉排序树的根指针
}
//二叉排序树查找递归算法
int BSTsearch1(BSTNode *T, int data)
{
BSTNode *p = T;
if(!p)
return 0;
else if(p->key == data)
return 1;
else if(p->key > data)
return BSTsearch1(p->lchild, data);
else
return BSTsearch1(p->rchild, data);
}
//二叉排序树查找非递归算法
int BSTsearch2(BSTNode *T, int data)
{
BSTNode *p = T;
while(p)
{
if(p->key == data)
return 1;
p = (p->key > data)? p->lchild : p->rchild;
}
return 0;
}
//中序遍历得到的是一个有序的序列,实现了排序功能
void Inorder(BSTNode *T)
{
if(T)
{
Inorder(T->lchild);
printf("%d ",T->key);
Inorder(T->rchild);
}
}
int main()
{
BSTNode *T = NULL;
int data1,data2;
T = CreateBST();
printf("以上述数建立的二叉排序树,中序遍历的结果:");
Inorder(T);
printf("\n输入待搜索的数据data1=");
scanf("%d", &data1);
//递归算法查找
if(BSTsearch1(T, data1))
printf("%d存在\n");
else
printf("%d不存在\n");
//非递归算法查找
if(BSTsearch2(T, data1))
printf("%d存在");
else
printf("%d不存在");
printf("\n输入待删除的数据data2=");
scanf("%d", &data2);
DelBST(T,data2);
printf("删除后的二叉排序树,中序遍历的结果:");
Inorder(T);
return 0;
}
对于删除操作的一点小改动的程序
//二叉排序树删除操作
void DelBST(BSTNode *T,int key)
{
BSTNode *p = T, *f, *q, *s;
while(p)
{
if(p->key == key) break; //找到关键字为key的结点
f=p;//记下关键字key节点的父节点
p=(key < p->key)? p->lchild : p->rchild;//分别在*p的左、右子树中查找
}
if(!p) return;//二叉排序树中无关键字为key的结点
if(p->lchild == NULL && p->rchild == NULL)//p无左子树无右子树
{
if(p == T) T = NULL;//删除的是根节点
else
if(p == f->lchild)
f->lchild = NULL;
else
f->rchild = NULL;
}
else if(p->lchild == NULL && p->rchild != NULL)//p无左子树有右子树
{
if(f->lchild == p)
f->lchild = p->rchild;
else
f->rchild = p->rchild;
}
else if(p->rchild == NULL && p->lchild != NULL)//p有左子树无右子树
{
if (f->lchild == p)
f->lchild = p->lchild;
else
f->rchild = p->lchild;
}
else if(p->lchild != NULL && p->rchild != NULL)//p既有左子树又有右子树
{
q = p;
s = p->lchild;
if(s->rchild == NULL)
{
q->key = s->key;
q->lchild = s->lchild;//重接q的左子树
}
else
{
while(s->rchild)
{//然后向右到尽头
q = s;
s = s->rchild;//s指向被删节点的“前驱”(中序前驱)
}
p->key = s->key;//以p的中序前趋结点s代替p(即把s的数据复制到p中
q->rchild = s->lchild;//重接q的右子树
}
}
}