1.简介
用平衡树实现二叉排序树的插入功能,用来构造二叉排序树;编写函数实现查找、遍历(三种遍历)、删除的操作。
2.代码
a.头文件及宏定义
#include "stdlib.h"
#include "iostream.h"
#define TRUE 1
#define ERROR 0
b.子程序
(1)数据结构及相关操作
typedef struct tnode
{
int dat;//数据域
int height;//节点自下向上高度
tnode *left;//左孩子
tnode *right;//右孩子
}tnode,*tree;//tnode可用于反映节点所需的存储空间
tnode* buynode(int key)//生成一个节点,返回生成节点的地址
{
tnode *ntemp=(tnode *)malloc(sizeof(tnode));
if(ntemp == NULL)
exit(0);//分配存储粗空间失败
ntemp->dat=key;
ntemp->left=NULL;
ntemp->right=NULL;
ntemp->height=1;
return ntemp;//返回生成节点的地址
}
(2)查找节点
bool search(tnode* now,int key,tnode* troot,tree &a)//now为当前所在的节点 troot在这里由于两种作用:1.找不到的情况返回父节点 2.树为空树时返回NULL(使用函数时该参数为null)
{
if (now==NULL)//找不到
{
a=troot;//左孩子或右孩子为空 则指向父节点
cout<<"node "<<key<<" does not exist"<<'\n';
return ERROR;
}
if (now->dat==key)//找到了
{
a=now;
return true;
}
else if (now->dat<key)
{
return search(now->right,key,now,a);//如果当前节点比键值小,在右孩子处搜索
}
return search(now->left,key,now,a);
}
(3)平衡化
int Max(int a,int b)//用于设置节点高度
if(a>b)
return a;
else
return b;
}
int Height(tnode* a)//获取当前节点高度
{
if (a==NULL)//叶子结点
{
return 0;
}
return a->height;
}
int getbalance(tnode* a)//获取平衡因子
{
if (a==NULL)//节点为空
{
return 0;
}
return Height(a->left)-Height(a->right);
}
tnode* rotateright(tnode* a)//右旋
{
tnode* y=a->left;//返回 RL左旋的节点(RL要先右旋再左旋) 或者 当前树的根节点
a->left=y->right;
y->right=a;
a->height=Max(Height(a->left),Height(a->left))+1;
y->height=Max(Height(y->left),Height(y->left))+1;
return y;
}
tnode* rotateleft(tnode* a)//左旋
{
tnode* y=a->right;
a->right=y->left;
y->left=a;
a->height=Max(Height(a->left),Height(a->left))+1;
y->height=Max(Height(y->left),Height(y->left))+1;
return y;
}
tnode* rebalance(tnode* a)//对二叉树进行平衡化
{
int balancefactor=getbalance(a);
if(balancefactor>1 && getbalance(a->left)>0)//LL 需经历一次平衡化
{
return rotateright(a);//右旋 返回左孩子
}
if(balancefactor>1 && getbalance(a->left)<=0)//LR 需经历两次平衡化
{
tnode* t=rotateleft(a->left);//先对左子树的右子树左旋 再对左子树右旋
a->left=t;
return rotateright(a);
}
if(balancefactor<-1 && getbalance(a->right)<=0)//RR 需经历一次平衡化
{
return rotateleft(a);//左旋 返回右孩子
}
if(balancefactor<-1 && getbalance(a->right)>0)//RL 需经历两次平衡化
{
tnode* t=rotateright(a->right);//先对右子树的左子树右旋 再对右子树左旋
a->right=t;
return rotateleft(a);
}
return a;
}
(4)插入节点
bool insert(tree &a,int key)//采用递归 此处也可使用二重指针
{
if (a == NULL)//如果孩子为空,则在此处插入
{
a=buynode(key);
}
//如果不为空树
else if (key>a->dat)
insert(a->right,key);
else if (key<a->dat)
insert(a->left,key);
else //查找到了
{
cout<<"node "<<key<<" has existed";
return false;
}
a->height=Max(Height(a->left),Height(a->right))+1;//递归 改变节点高度
a=rebalance(a);//递归将树平衡化
return true;
}
(4)删除节点
tnode* MinNode(tnode* a)//递归找最小节点
{
if(a->left == NULL)
return a;
return MinNode(a->left);
}
tnode* deleteMin(tnode* a)//删除最小节点 返回删除完最小节点后的树
{
if(a->left==NULL)//当前节点为最小节点 将右孩子接到上一层的左边
return a->right;
a->left=deleteMin(a->left);//不为最小节点 继续在左子树上找
return a;//当前节点不为最小节点 将自己接在上一层的左边
}
tnode* Delete(tree& a,int key)//删除节点
{
if (a == NULL)//不存在该节点
{
cout<<"node "<<key<<" does not exist"<<'\n';
return NULL;
}
//没找到 则继续在要删除的子树上找节点
if (key>a->dat)
a->right=Delete(a->right,key);
else if (key<a->dat)
a->left=Delete(a->left,key);
else //查找到了 返回删除后的子树(返回继承节点) 接在递归的上一层的节点上
{
if (a->left == NULL)//待删除节点左子树为空
{
return a->right;
}
else if(a->right == NULL)//待删除节点右子树为空
{
return a->left;
}
//左右节点都不为空
tnode* inherit=MinNode(a->right);//继承节点为要删除的节点右子树中最小的节点
inherit->right=deleteMin(a->right);//删除右子树中最小的节点 并接在继承节点的右子树上
inherit->left=a->left;//将要删除的节点的左子树接在继承节点的左子树上
a=inherit;
}
a->height=Max(Height(a->left),Height(a->right))+1;//递归 改变节点高度
a=rebalance(a);//递归将树平衡化
return a;
}
(5)遍历
void preodertraverse(tnode* a)//前序
{
if(a)
{
cout<<a->dat<<' ';
preodertraverse(a->left);
preodertraverse(a->right);
}
}
void ineodertraverse(tnode* a)//中序
{
if(a)
{
ineodertraverse(a->left);
cout<<a->dat<<' ';
ineodertraverse(a->right);
}
}
void postodertraverse(tnode* a)//后序
{
if(a)
{
postodertraverse(a->left);
postodertraverse(a->right);
cout<<a->dat<<' ';
}
}
b.主程序
void main()
{
tnode* a=NULL;//给一颗空树
tnode* Search;//用于存储搜索的指针
insert(a,2);
insert(a,1);
insert(a,0);
insert(a,3);
insert(a,4);
insert(a,5);
preodertraverse(a);
cout<<'\n';
ineodertraverse(a);
cout<<'\n';
Delete(a,4);
Delete(a,3);
Delete(a,6);
preodertraverse(a);
cout<<'\n';
ineodertraverse(a);
cout<<'\n';
search(a,3,NULL,Search);
search(a,0,NULL,Search);
cout<<Search->dat<<'\n';
}