课设(二)二叉(平衡)排序树

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';
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值