hello,大家好我是新手小白,今日学习到平衡二叉树,就复习了一下。并在此与大家分享!对于平衡二叉树的思想可以先借阅方法一所说书籍或者其他作者的文章!
我将从两个方法进行讲解及其代码内容 进行展示,方法一是我学习课程书上的,方法二是我在上课时候根据现在时代拥有大存储空间的特点联想引发出来的。
首先我先简单讲解下方法一:
方法一的思想出自人民邮电出版社《数据结构》(C语言版 第2版),严蔚敏、李冬梅、吴伟民编著。从四个方面对平衡二叉树进行了分析,分别为LL、RR、LR、RL四种类型进行了思想讲解。
方法二:
方法二的思想是,通过中序遍历(因为,中序遍历输出是从小到大!)将树的各个节点一一打入线性表。后通过线性表重构平衡二叉树(重构方法源自折半查找 和 树的先序遍历数组及中序遍历数组构造二叉树 两个算法的思想启发)
接下来是代码展示部分:
#include<iostream>
using namespace std;
#define OK 1
#define ERROR 0
#define MaxInt 100
typedef int Status;
typedef int ElemType;
//树的结构
typedef struct BNode{
ElemType data;
BNode *lchild,*rchild;
}BNode,*BTree;
Status CreateBTree(BTree &T,ElemType e)//建树
{
T=new BNode;
T->data=e;
T->lchild=T->rchild=NULL;
return OK;
}
void PushBTree(BTree &T,ElemType e)//将元素打进树
{
if(!T)
CreateBTree(T,e);
else if(T->data>e)
PushBTree(T->lchild,e);
else
PushBTree(T->rchild,e);
}
void PrintBTree1(BTree T)//先序输出树
{
if(!T)
return ;
cout<<T->data<<" ";
PrintBTree1(T->lchild);
PrintBTree1(T->rchild);
}
void PrintBTree2(BTree T)//中序输出树
{
if(!T)
return ;
PrintBTree2(T->lchild);
cout<<T->data<<" ";
PrintBTree2(T->rchild);
}
/*********************方法一************************/
int Fun(BTree &T,int aver,int k)//LL、RR、RL、LR四种方法的转动
{
BTree p,pre;
p=T;
if(aver>0&&k>0)
{
T=T->lchild;
p->lchild=T->rchild;
T->rchild=p;
return 1;
}
if(aver<0&&k<0)
{
T=T->rchild;
p->rchild=T->lchild;
T->lchild=p;
return 1;
}
if(aver>0&&k<0)
{
p=T->lchild->rchild;
pre=T->lchild;
pre->rchild=p->lchild;
T->lchild=p->rchild;
p->lchild=pre;
p->rchild=T;
T=p;
return 1;
}
if(aver<0&&k>0)
{
p=T->rchild->lchild;
pre=T->rchild;
pre->lchild=p->rchild;
T->rchild=p->lchild;
p->lchild=T;
p->rchild=pre;
T=p;
return 1;
}
}
int high(BTree &T,int &aver)//以求树的深度函数为基础,叠加平衡因子,再判断是否需要转动
{
int m,n,l,r,c=0;
if(!T)
return 0;
m=high(T->lchild,l);
n=high(T->rchild,r);
aver=m-n;
if(aver>1)
c=Fun(T,aver,l);
else if(aver<-1)
c=Fun(T,aver,r);
if(c)
{
//high(T,aver);
m=high(T->lchild,l);
n=high(T->rchild,r);
}
return aver>=0?m+1:n+1;
}
/************************************************/
/***********************方法二********************/
//线性表的结构
typedef struct List{
BTree *elem;//元素类型为树结构类型
int length;
}SqList;
Status CreateSqList(SqList &L)//线性表的初始化
{
L.elem=new BTree[MaxInt];
L.length=0;
return OK;
}
Status PushSqList(SqList &L,BTree T)//将树的各个节点打入线性表
{
if(!T)
return OK;
PushSqList(L,T->lchild);
L.elem[L.length++]=T; //这里为树的中序遍历打线性表(原因:中序遍历的结构具有从大到小的
PushSqList(L,T->rchild); //特点)
T->lchild=NULL;//注意这两句话,将每个节点化为独立的节点
T->rchild=NULL;//在此处做此动作可以节省后面的考虑
}
Status SqList_CreateBTree(SqList L,int rear,int top,BTree &T)//通过线性表重构树
{
int w;
if(top>rear)
return OK;
w=(top+rear)/2; //折半查找的思想
T=L.elem[w];
SqList_CreateBTree(L,w-1,top,T->lchild); //这两行的思想类似通过树的先序遍历数组和中序遍
SqList_CreateBTree(L,rear,w+1,T->rchild); //历数组重构树的思想
}
/******************************************************/
main()
{
int n,i,aver;
ElemType data;
BTree T=NULL;
SqList L;
//CreateSqList(L);
cout<<"输入节点数,并一一输入节点元素(int)"<<endl;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>data;
PushBTree(T,data);
high(T,aver);//方法一
}
/*方法二
PushSqList(L,T);
SqList_CreateBTree(L,L.length-1,0,T);
*/
cout<<"先序遍历"<<endl;
PrintBTree1(T);
cout<<endl;
cout<<"中序遍历"<<endl;
PrintBTree2(T);
cout<<endl;
}
谢谢大家观看!