|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 零度非安全 于 2015-12-3 21:30 编辑
哈喽,各位鱼油们你们好,由于最近在忙各种课程作业,所以很少上论坛,今天有幸跟各位鱼油来分享下关于平衡二叉树算法的实现
早在之前,小甲鱼老师已经在《数据结构与算法》中提到了关于平衡二叉树的讲解,当时我也看的稀里糊涂的,完全不知道他在讲什么?但是这个学期我们也在学这门课程,所以呢,我花了几天的时间写了个关于平衡二叉树的算法,个人觉得还算可以,如果有谁看了我写的算法后,觉得某些地方需要改动的话,请跟帖回复
如果有人提出较好的意见的,我会给额外的奖励滴
代码共计478行,代码如下:
- #include<stdio.h>
- #include<stdlib.h>
- #include<malloc.h>
- #define MaxSize 100
- #define MaxWith 50
- typedef int KeyType;
- typedef char InfoType;
- /*定义各节点的类型*/
- typedef struct node
- {
- KeyType key; /*关键字项*/
- int bf; /*增加的平衡因子*/
- InfoType data; /*其它的数据与域*/
- struct node *lchild; /*左孩子指针*/
- struct node *rchild; /*右孩子指针*/
- }AVLNode; /*AVL树中节点类型定义*/
- int m = 0;
- AVLNode *b = NULL; /*定义全局变量m、*b*/
- /*左平衡旋转情况处理*/
- void LeftProcess(AVLNode *&p, int &taller)
- {
- AVLNode *p1, *p2;
- if (p->bf == 0) /*当左右子树等高时插入使树高度增加*/
- {
- p->bf = 1;
- taller = 1; /*所以平衡因子置为1,高度为1*/
- }
- else if (p->bf == -1) /*当右子树比左子树高,插入后左右子树等高*/
- {
- p->bf = 0;
- taller = 0; /*所以平衡因子置为0,高度为0*/
- }
- else /*当左子树比右子树高时插入则需做左平衡处理*/
- {
- p1 = p->lchild;
- if (p1->bf == 1) /*当插入到左孩子的左子树上时需做LL处理*/
- {
- p->lchild = p1->rchild;
- p1->rchild = p;
- p->bf = p1->bf = 0;
- p = p1;
- }
- else if (p1->bf == -1) /*当插入到左孩子的右子树上时需做LR处理*/
- {
- p2 = p1->rchild;
- p1->rchild = p2->lchild;
- p2->lchild = p1;
- p->lchild = p2->rchild;
- p2->rchild = p;
- p = p2; /*将p指向新的根节点,并置bf的值为0*/
- p->bf = 0;
- }
- taller = 0;
- }
- }
- /*右平衡旋转情况处理*/
- void RightProcess(AVLNode *&p, int &taller) /*操作类似上面,请参照左平衡旋转处理*/
- {
- AVLNode *p1, *p2;
- if (p->bf == 0)
- {
- p->bf = -1;
- taller = 1;
- }
- else if (p->bf == 1)
- {
- p->bf = 0;
- taller = 0;
- }
- else
- {
- p1 = p->rchild;
- if (p1->bf == -1)
- {
- p->rchild = p1->lchild;
- p1->lchild = p;
- p->bf = p1->bf = 0;
- p = p1;
- }
- else if (p1->bf == 1)
- {
- p2 = p1->lchild;
- p1->lchild = p2->rchild;
- p2->rchild = p1;
- p->rchild = p2->lchild;
- p2->lchild = p;
- p = p2;
- p->bf = 0;
- }
- taller = 0;
- }
- }
- /*在进行删除平衡二叉树的节点时候需要做相应的左平衡旋转处理*/
- void LeftProcess1(AVLNode *&p, int &taller)
- {
- AVLNode *p1, *p2;
- if (p->bf == 1)
- {
- p->bf = 0;
- taller = 1;
- }
- else if (p->bf == 0)
- {
- p->bf = -1;
- taller = 0;
- }
- else
- {
- p1 = p->rchild; /*RR处理*/
- if (p1->bf == 0)
- {
- p->rchild = p1->lchild;
- p1->rchild = p;
- p1->bf = 1;
- p->bf = -1;
- p = p1;
- taller = 0;
- }
- else if (p1->bf == -1) /*RR处理*/
- {
- p->rchild = p1->lchild;
- p1->lchild = p;
- p->bf = p1->bf = 0;
- p = p1;
- taller = 1;
- }
- else /*RL处理*/
- {
- p2 = p1->lchild;
- p1->lchild = p2->rchild;
- p2->rchild = p1;
- p->rchild = p2->lchild;
- p2->lchild = p;
- p2->bf = 0;
- p = p2;
- taller = 1;
- }
- }
- }
- /*在进行删除平衡二叉树的节点时候需要做相应的右平衡旋转处理*/
- void RightProcess1(AVLNode *&p, int &taller)
- {
- AVLNode *p1, *p2;
- if (p->bf == -1)
- {
- p->bf = 0;
- taller = -1;
- }
- else if (p->bf == 0)
- {
- p->bf = 1;
- taller = 0;
- }
- else /*LL处理*/
- {
- p1 = p->lchild;
- if (p1->bf == 0)
- {
- p->lchild = p1->rchild;
- p1->rchild = p;
- p->bf = -1;
- p1->bf = 1;
- p = p1;
- taller = 0;
- }
- else if (p1->bf == 1) /*LL处理*/
- {
- p->lchild = p1->rchild;
- p1->rchild = p;
- p->bf = p1->bf = 0;
- p = p1;
- taller = 1;
- }
- else /*LR处理*/
- {
- p2 = p1->rchild = p2->lchild;
- p2->lchild = p1;
- p->lchild = p2->rchild;
- p2->rchild = p;
- p2->bf = 0;
- p = p2;
- taller = 1;
- }
- }
- }
- void Delete2(AVLNode *q, AVLNode *&r, int &taller) /*用于被删除节点左右子树均不为空*/
- {
- if (r->rchild == NULL)
- {
- q->key = r->key;
- q = r;
- r = r->lchild;
- free(q);
- taller = 1;
- }
- else
- {
- Delete2(q, r->rchild, taller);
- if (taller == 1)
- RightProcess(r, taller);
- }
- }
- /*删除平衡二叉树的节点*/
- int DeleteAVL(AVLNode *&p, KeyType x, int &taller)
- {
- int k;
- AVLNode *q;
- if (p == NULL) /*如果为空树,则正常退出*/
- return 0;
- else if (x < p->key) /*如果待删除的节点小于该节点,则往它左孩子寻找*/
- {
- k = DeleteAVL(p->lchild, x, taller);
- if (taller == 1) /**/
- LeftProcess(p, taller);
- return k;
- }
- else if (x > p->key)
- {
- k = DeleteAVL(p->rchild, x, taller);
- if (taller == 1)
- RightProcess1(p, taller);
- return k;
- }
- else
- {
- q = p;
- if (p->rchild == NULL) /*被删节点右子树为空*/
- {
- p = p->lchild;
- free(q);
- taller = 1;
- }
- else if (p->rchild == NULL) /*被删节点左子树为空*/
- {
- p = p->lchild;
- free(q);
- taller = 1;
- }
- else /*被删节点左右子树均不为空*/
- {
- Delete2(q, q->lchild, taller);
- if (taller == 1)
- LeftProcess1(q, taller);
- p = q;
- }
- return 1;
- }
- }
- /*销毁平衡二叉树*/
- void DestroyAVL(AVLNode *&b)
- {
- if (b->lchild)
- DestroyAVL(b->lchild);
- if (b->rchild)
- DestroyAVL(b->rchild);
- free(b);
- b = NULL;
- }
- /*向当前平衡二叉树插入一个元素*/
- int InsertNode(AVLNode *&b, KeyType e, int &taller)
- {
- if (b == NULL) /*当b为空树时进行动态分配等待插入新元素*/
- {
- b = (AVLNode *)malloc(sizeof(AVLNode));
- b->key = e;
- b->lchild = b->rchild = NULL;
- b->bf = 0; /*将平衡因子置为 0*/
- taller = 1; /*将该节点的高度置为 1*/
- }
- else
- {
- if (e == b->key) /*如果树中已经存在该点,则无需插入*/
- {
- taller = 0;
- return 0;
- }
- if (e < b->key) /*如果待插入的数小于该节点,则往它左孩子插入*/
- {
- if ((InsertNode(b->lchild, e, taller)) == 0)
- return 0;
- if (taller == 1) /*若该节点的高度为1,插入后增1,则会破坏平衡*/
- LeftProcess(b, taller); /*破坏后进行左平衡旋转处理重新达到平衡*/
- }
- else /*否则往它右孩子插入*/
- {
- if ((InsertNode(b->rchild, e, taller)) == 0)
- return 0;
- if (taller == 1) /*若该节点的高度为1,插入后增1,则会破坏平衡*/
- RightProcess(b, taller); /*破坏后进行右平衡旋转处理重新达到平衡*/
- }
- }
- return 1;
- }
- /*输出要选择操作的功能菜单*/
- void OutputAVL(AVLNode *b)
- {
- system("cls");
- system("color a");
- printf("\t\t******************************************\n");
- printf("\t\t* 平衡二叉树操作 *\n");
- printf("\t\t* ==请 选 择 你 的 操 作== *\n");
- printf("\t\t* *\n");
- printf("\t\t* A.创 建 *\n");
- printf("\t\t* B.显 示 *\n");
- printf("\t\t* C.查 找 *\n");
- printf("\t\t* D.插 入 *\n");
- printf("\t\t* E.删 除 *\n");
- printf("\t\t* F.销 毁 *\n");
- printf("\t\t* G.退 出 *\n");
- printf("\t\t* *\n");
- printf("\t\t* 爱鱼C、爱编程、爱世界、爱和平 *\n");
- printf("\t\t* www.bbs.fishc.com *\n");
- printf("\t\t* ---By:零度非安全 *\n");
- printf("\t\t******************************************\n");
- }
- /*递归查找平衡二叉树中的元素*/
- bool SearchAVLNode(AVLNode *&b, int n)
- {
- if (!b)
- return false;
- else if (n == b->key) /*找到了返回true*/
- return true;
- else if (n < b->key)
- return SearchAVLNode(b->lchild, n); /*如果小于则继续在其左孩子中查找*/
- else
- return SearchAVLNode(b->rchild, n); /*否则就到右孩子中查找*/
- }
- /*打印平衡二叉树的状态*/
- void PrintAVLNode(AVLNode *b)
- {
- AVLNode *p, *St[MaxSize];
- int level[MaxSize][2], top, n, i, width = 4;
- if (b != NULL)
- {
- top = 1;
- St[top] = b; /*将根节点入栈*/
- level[top][0] = width;
- while (top > 0)
- {
- p = St[top];
- n = level[top][0];
- for (i = 1; i <= n; i++)
- printf(" ");
- printf("%d", p->key);
- for (i = n + 1; i < MaxSize - 6; i += 2)
- printf("*");
- printf("\n");
- top--;
- if (p->rchild != NULL) /*将右孩子根节点入栈*/
- {
- top++;
- St[top] = p->rchild;
- level[top][0] = n + width;
- }
- if (p->lchild != NULL) /*将左孩子根节点入栈*/
- {
- top++;
- St[top] = p->lchild;
- level[top][0] = n + width;
- }
- }
- }
- }
- /*创建一个平衡二叉树*/
- AVLNode *CreateAVL(AVLNode *&b)
- {
- int mainkey, i;
- b = NULL;
- printf("请输入节点(以-1结束):");
- scanf("%d", &mainkey);
- while (mainkey != -1) /*当输入的数不为-1时进行循环*/
- {
- InsertNode(b, mainkey, i);
- printf("当前二叉树状态:\n");
- PrintAVLNode(b);
- printf("请输入节点(以-1结束):");
- scanf("%d", &mainkey);
- }
- return b;
- }
- /*主函数*/
- int main()
- {
- int node, h;
- char ch; /*定义一个输入变量*/
- while (1) /*进行循环操作*/
- {
- OutputAVL(b);
- printf("请选择:");
- ch = getchar();
- fflush(stdin); /*清除输入的缓存*/
- if (ch == 'A') /*进行创建操作*/
- {
- system("cls");
- printf("正在创建中......\n\n");
- CreateAVL(b);
- system("pause");
- }
- else if (ch == 'B') /*进行显示操作*/
- {
- system("cls");
- printf("当前平衡二叉树的状态为:\n");
- PrintAVLNode(b);
- system("pause");
- }
- else if (ch == 'C') /*进行查找操作*/
- {
- system("cls");
- printf("正在查找中......\n\n");
- printf("请输入要查找的关键字:\n");
- scanf("%d", &node);
- if (SearchAVLNode(b, node))
- {
- printf("查找成功!\n");
- PrintAVLNode(b); /*当查找成功时输出当前平衡二叉树的状态*/
- }
- else
- {
- printf("查找失败!\n");
- printf("当前平衡二叉树中根本不存在这个节点\n"); /*当查找失败提示用户这树中不存在该节点*/
- }
- system("pause");
- }
- else if (ch == 'D') /*进行插入操作*/
- {
- system("cls");
- printf("正在插入中......\n\n");
- printf("请输入关键字(整数):\n");
- scanf("%d", &node);
- InsertNode(b, node, h);
- system("pause");
- }
- else if (ch == 'E') /*进行删除操作*/
- {
- system("cls");
- printf("正在删除中......\n\n");
- printf("请输入关键字(整数):\n");
- scanf("%d", &node);
- if (DeleteAVL(b, node, h))
- {
- printf("删除成功!\n");
- PrintAVLNode(b); /*当删除成功时及时显示当前平衡二叉树状态*/
- }
- else
- printf("删除失败!\n");
- system("pause");
- }
- else if (ch == 'F') /*进行销毁操作*/
- {
- system("cls");
- printf("正在销毁中......\n\n");
- DestroyAVL(b);
- printf("销毁成功!\n");
- system("pause");
- }
- else if (ch == 'G') /*进行退出操作*/
- exit(0);
- OutputAVL(b);
- fflush(stdin);
- }
- return 0; /*程序正常退出*/
- }
复制代码
源码文件:
平衡二叉树源码文件.rar
(9.05 KB, 下载次数: 42)
程序文件:
平衡二叉树演示.rar
(17.2 KB, 下载次数: 23)
|
评分
-
参与人数 1 | 荣誉 +10 |
鱼币 +10 |
贡献 +10 |
收起
理由
|
康小泡
| + 10 |
+ 10 |
+ 10 |
支持楼主! |
查看全部评分
|