1、平衡二叉树一、 问题描述:建立一个平衡二叉树,要求做增删查改的操作二、 概要设计定义一个节点存贮结构,包含权值以及平衡因子的值,平衡因子的值的绝对值为=1时,则为平衡,否则需要调平,多种调平动作三、 详细设计弄清楚增加节点和删除节点的情况,分情况讨论要求将所有的情况考虑进去然后根据最基本的四种结构左左 右右 左右 右左 进行调平四、 测试及结果五、 心得体会通过这次试验我明白了两种算法的差异以及实现的机制,算法之巧妙着实让我弄了很长一段时间源代码清单Function.cpp#include stdafx.h#includefunction.h/创建二叉树以-32767结束void CreatB
2、T(BTree &T) int m; int i; bool taller = false; T = NULL; /初始化树为空 cout请输入关键字(且以-32767为结束建立二叉树):i; getchar(); while(i != -32767) InsertBT(T,i,taller); cout请输入关键字(以-32767结束创建二叉树):i; getchar(); taller = false; m = 0; cout您创建的二叉树为:endl; PrintBT(T,m);/直接创建平衡二叉树void Creat_AVL(BTree &T) int m; int i; bool t
3、aller=false; T = NULL; cout 请输入关键字(以-32767结束建立平衡二叉树):endl; scanf(%d,&i); getchar(); while(i != -32767) SetAVL(T,i,taller); cout 请输入关键字(以-32767结束建立平衡二叉树):i; getchar(); taller=false; m=0; cout平衡二叉树创建结束. endl; if(T) PrintBT(T,m); else cout这是一棵空树. rchild) PrintBT(T-rchild,m+1); for(i = 1;i=m;i+) cout ;
4、/打印i个空格用来表示出层次 coutdatalchild) PrintBT(T-lchild,m+1); /对*p为根的进行右旋转处理void Right_Balance(BTree &p) BTree lc; lc = p-lchild; /lc指向的*p左子树根结点 p-lchild = lc-rchild; /lc的右子树挂接为*p的左子树 lc-rchild = p; p = lc; /p指向新的结点/对以*p为根的二叉排序树作左旋处理void Left_Balance(BTree &p) BTree rc; rc = p-rchild; /指向的*p右子树根结点 p-rchild
5、= rc-lchild; /rc左子树挂接到*p的右子树 rc-lchild = p; p = rc; /p指向新的结点/对以指针T所指结点为根的二叉树作左平衡旋转处理void Left_Root_Balance(BTree &T) /左左型 和左右型 BTree lc,rd; lc = T-lchild; /指向*T的左子树根结点 switch(lc-bf) /检查*T的左子树的平衡度,并作相应平衡处理 case LH: /新结点插入在*T的左孩子的左子树上,要作单右旋处理 T-bf = lc-bf = EH; Right_Balance(T); break; case RH: /新结点插入
6、在*T的左孩子的右子树上,要作双旋处理 rd = lc-rchild; /rd指向*T的左孩子的右子树根 switch(rd-bf) /修改*T及其左孩子的平衡因子 case LH: T-bf = RH; lc-bf = EH; break; case EH: T-bf = lc-bf = EH; break; case RH: T-bf = EH; lc-bf = LH; break; rd-bf = EH; Left_Balance(T-lchild); /对*T的左子树作左旋平衡处理 Right_Balance(T); /对*T作右旋平衡处理 /对以指针T所指结点为根的二叉树作右平衡旋转
7、处理void Right_Root_Balance(BTree &T) BTree rc,ld; rc = T-rchild; /指向*T的右子树的根节点 switch(rc-bf) case RH: /新节点插在*T T-bf = rc-bf = EH; Left_Balance(T); break; case LH: ld = rc-lchild; /ld指向*T的右孩子的左子树根 switch(ld-bf) case LH: T-bf = EH; rc-bf = RH; break; case EH: T-bf = rc-bf = EH; break; case RH: T-bf = L
8、H; rc-bf = EH; break; ld-bf = EH; Right_Balance(T-rchild);/对*T的右子树作左旋平衡处理 Left_Balance(T); /对*T作左旋平衡处理 /插入结点i,若T中存在和i相同关键字的结点,则插入一个数据元素为i的新结点,并返回,否则返回bool InsertBT(BTree &T,int i,bool &taller) if(!T)/插入新结点,树“长高”,置taller为true T = (BTree)malloc(sizeof(BTNode); T-data = i; T-lchild = T-rchild =NULL; T-
9、bf = EH; /置平衡因子为零 taller = true; else if(ET(i,T-data) /树中已存在和有相同关键字的结点是否i = T-data taller = false; / 将taller置为false表示插入失败 cout已存在相同关键字的结点data) /应继续在*T的左子树中进行搜索 if(!InsertBT(T-lchild,i,taller) return 0; else /应继续在*T的右子树中进行搜索 if(!InsertBT(T-rchild,i,taller) return 0; return 1;/*删除结点时左平衡旋转处理*/void Left
10、_Root_Balance_det(BTree &p,int &shorter) BTree p1,p2; if(p-bf=1) /p结点的左子树高,删除结点后p的bf减,树变矮 p-bf=0; shorter=1; else if(p-bf=0)/p结点左、右子树等高,删除结点后p的bf减,树高不变 p-bf=-1; shorter=0; else /p结点的右子树高 p1=p-rchild;/p1指向p的右子树 if(p1-bf=0)/p1结点左、右子树等高,删除结点后p的bf为-2,进行左旋处理,树高不变 Left_Balance(p); p1-bf=1; p-bf=-1; shorte
11、r=0; else if(p1-bf=-1)/p1的右子树高,左旋处理后,树变矮 Left_Balance(p); p1-bf=p-bf=0; shorter=1; else /p1的左子树高,进行双旋处理(先右旋后左旋),树变矮 p2=p1-lchild; p1-lchild=p2-rchild; p2-rchild=p1; p-rchild=p2-lchild; p2-lchild=p; if(p2-bf=0) p-bf=0; p1-bf=0; else if(p2-bf=-1) p-bf=1; p1-bf=0; else p-bf=0; p1-bf=-1; p2-bf=0; p=p2;
12、shorter=1; /*删除结点时右平衡旋转处理*/void Right_Root_Balance_det(BTree &p,int &shorter) BTree p1,p2; if(p-bf=-1) p-bf=0; shorter=1; else if(p-bf=0) p-bf=1; shorter=0; else p1=p-lchild; if(p1-bf=0) Right_Balance(p); p1-bf=-1; p-bf=1; shorter=0; else if(p1-bf=1) Right_Balance(p); p1-bf=p-bf=0; shorter=1; else p
13、2=p1-rchild; p1-rchild=p2-lchild; p2-lchild=p1; p-lchild=p2-rchild; p2-rchild=p; if(p2-bf=0) p-bf=0; p1-bf=0; else if(p2-bf=1) p-bf=-1; p1-bf=0; else p-bf=0; p1-bf=1; p2-bf=0; p=p2; shorter=1; /*删除结点*/void Delete(BTree q,BTree &r,int &shorter) if(r-rchild=NULL) q-data=r-data; q=r; r=r-lchild; free(q
14、); shorter=1; else Delete(q,r-rchild,shorter); if(shorter=1) Right_Root_Balance_det(r,shorter); /*二叉树的删除操作*/int DeleteAVL(BTree &p,int x,int &shorter) int k; BTree q; if(p=NULL) cout不存在要删除的关键字! endl; return 0; else if(xdata)/在p的左子树中进行删除 k=DeleteAVL(p-lchild,x,shorter); if(shorter=1) Left_Root_Balanc
15、e_det(p,shorter); return k; else if(xp-data)/在p的右子树中进行删除 k=DeleteAVL(p-rchild,x,shorter); if(shorter=1) Right_Root_Balance_det(p,shorter); return k; else q=p; if(p-rchild=NULL) /右子树空则只需重接它的左子树 p=p-lchild; free(q); shorter=1; else if(p-lchild=NULL)/左子树空则只需重接它的右子树 p=p-rchild; free(q); shorter=1; else/
16、左右子树均不空 Delete(q,q-lchild,shorter); if(shorter=1) Left_Root_Balance_det(p,shorter); p=q; return 1; /*调平二叉树具体方法*/bool SetAVL(BTree &T,int i,bool &taller) if(!T)/插入新结点,树“长高”,置taller为true T = (BTree)malloc(sizeof(BTNode); T-data = i; T-lchild = T-rchild =NULL; T-bf = EH; taller = true; else if(ET(i,T-d
17、ata) /树中已存在和有相同关键字的结点 taller = false; cout已存在相同关键字的结点data) /应继续在*T的左子树中进行搜索 if(!SetAVL(T-lchild,i,taller) return 0; if(taller) /已插入到*T的左子树中且左子树“长高” switch(T-bf) /检查*T的平衡度 case LH: /原本左子树比右子树高,需要作左平衡处理 Left_Root_Balance(T); taller = false; break; case EH: /原本左子树、右子等高,现因左子树增高而使树增高 T-bf = LH; taller =
18、true; break; case RH: /原本右子树比左子树高,现左、右子树等高 T-bf = EH; taller = false; break; else /应继续在*T的右子树中进行搜索 if(!SetAVL(T-rchild,i,taller) return 0; if(taller) /已插入到*T的右子树中且右子树“长高” switch(T-bf) /检查*T的平衡度 case LH: /原本左子树比右子树高,现左、右子树等高 T-bf = EH; taller = false; break; case EH: /原本左子树、右子等高,现因右子树增高而使树增高 T-bf = R
19、H; taller = true; break; case RH: /原本右子树比左子树高,需要作右平衡处理 Right_Root_Balance(T); taller = false; break; return 1; Main函数:/ 平衡二叉树.cpp : 定义控制台应用程序的入口点。/#include stdafx.h#include function.hint _tmain(int argc, _TCHAR* argv) system(color 9f); system(mode con: cols=100 lines=40); int input,m; char search; b
20、ool taller=false; int shorter=0; BTree T; T=(BTree)malloc(sizeof(BTNode); T=NULL; while(1) coutn请选择需要的二叉树操作nendl; cout1.创建二叉树.增加新结点.直接创建平衡二叉树.在平衡二叉树上增加新结点并调平衡.删除.退出ninput; getchar(); switch(input) case 1: CreatBT(T); break; case 2: cout请输入你要增加的关键字search; getchar(); InsertBT(T,search,taller); m = 0;
21、PrintBT(T,m); break; case 3: Creat_AVL(T); break; case 4: cout请输入你要增加的关键字endl; coutsearch; getchar(); SetAVL(T,search,taller); m = 0; PrintBT(T,m); break; case 5: cout请输入你要删除的关键字; scanf(%d,&search); getchar(); DeleteAVL(T,search,shorter); m=0; PrintBT(T,m); break; case 0: break; default: cout输入错误,请重
22、新选择。; break; if(input = 0) break; cout按任意键继续.; getchar(); return 0; Function.h#include #include #include using namespace std;/定义树的结点类型typedef struct BTNode int data; int bf; /平衡因子 struct BTNode *lchild,*rchild; /左、右孩子BTNode,*BTree; #define LH +1 /Left Height左高#define EH 0 /Equal Height相同的高度#define R
23、H -1 /Right Height High右高#define ET(a,b) (a) = (b) /a=b#define LT(a,b) (a) (b) /a (b) /ab/需要的函数声明void CreatBT(BTree &T); /创建二叉树以#结束void Right_Balance(BTree &p); /对*p为根进行右旋转处理void Left_Balance(BTree &p); /对*p为根的进行左旋转处理void Left_Root_Balance(BTree &T); /对*T所指节点为根的二叉树作左旋转调平void Right_Root_Balance(BTree
24、 &T); /对*T所指结点为根的二叉树作右旋转调平bool InsertBT(BTree &T,int i,bool &taller); /插入节点,若结点中存在该点则返回值为否则的话void Delete(BTree q,BTree &r,int &shorter); /删除某个节点void Left_Root_Balance_det(BTree &p,int &shorter); /删除某个节点进行平衡二叉树左平衡转void Right_Root_Balance_det(BTree &p,int &shorter); /删除某个节点进行平衡二叉树右平衡调int DeleteAVL(BTree &p,int x,int &shorter); /删除整个二叉树void Creat_AVL(BTree &T); /直接创建平衡二叉树bool SetAVL(BTree &T,int i,bool &taller); /二叉树的调平情况分类进行调平函数void PrintBT(BTree T,i
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1