#include <stdio.h>
#include <malloc.h>
#include<stdlib.h>

#define EQ(a,b) ((a)==(b))
#define LT(a,b)  ((a)<(b))
#define LQ(a,b)  ((a)>(b))
#define LH +1     //左高
#define EH 0      //等高
#define RH -1     //右高
#define NULL 0

//http://1wangxiaobo@163.com
/////////////////////////// 定义结构体 /////////////////////////// 
typedef struct BSTNode
{
    int data;
    int bf;                        //结点的平衡因子
    struct BSTNode *lchild,*rchild;//左、右孩子指针
}BSTNode,*BSTree;

///////////////////////////  函数声明  ///////////////////////////
void R_Rotate(BSTree &p);    //对以*p为根的二叉排序树作右旋处理
void L_Rotate(BSTree &p);    //对以*p为根的二叉排序树作左旋处理
void LeftBalance(BSTree &T); //对以指针T所指结点为根的二叉树作左平衡旋转处理
void RightBalance(BSTree &T);//对以指针T所指结点为根的二叉树作右平衡旋转处理
bool InsertAVL(BSTree &T,int e,bool &taller);//插入结点e
bool SearchBST(BSTree &T,int key);//查找元素key是否在树T中
void PrintBST(BSTree T,int m);//按树状打印输出二叉树的元素
void CreatBST(BSTree &T);    //创建平衡二叉树,(注意:以输入-1为二叉树建立的结束)
void LeftBalance_div(BSTree &p,int &shorter);//删除结点时左平衡旋转处理
void RightBalance_div(BSTree &p,int &shorter);//删除结点时右平衡旋转处理
void Delete(BSTree q,BSTree  &r,int &shorter);//删除结点
int DeleteAVL(BSTree &p,int x,int &shorter);//平衡二叉树的删除操作

/////////////////////////////////////////////////////////////////////

void main()

    int input,search,m;
    bool taller=false;
 int shorter=0;
    BSTree T,T1,T2;
    T=(BSTree)malloc(sizeof(BSTNode));
    T=T1=T2=NULL;
 while(1)
 {   system("cls"); 
    printf("             ******************************************\n");
 printf(" ╱◥██◣  *1.创建\t2.查找\t3.插入\t4.删除\t5.退出*\n");
    printf("|田|田田│ ******************************************\n");
    printf("╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬╬<平衡二叉树 >\n");
        printf("请输入您所需的操作功能:\t");
        scanf("%d",&input);getchar();   
  switch(input)
  {
     case 1:
      CreatBST(T); break;
     case 2:
      printf("请输入你要查找的关键字");
               scanf("%d",&search); getchar();
               if(SearchBST(T,search)) printf("该二叉树中存在关键字%d,查找成功!\n",search);
               else printf("查找失败!\n");
               break;
     case 3:
               printf("请输入你要插入的关键字");
               scanf("%d",&search); getchar();
               InsertAVL(T,search,taller); m = 0;
      PrintBST(T,m); break;
     case 4:
      printf("请输入你要删除的关键字");
      scanf("%d",&search); getchar();
      DeleteAVL(T,search,shorter);
      m=0; PrintBST(T,m); break;
     case 5:
               printf("\t\tbyebye!\n");break;
     default:printf("输入错误,请重新选择。");break;
  }
  if(input == 5) break;
  printf("\t\t按任意键继续..."); getchar();
 }

}

//对以*p为根的二叉排序树作右旋处理
void R_Rotate(BSTree &p) 
{
    BSTree lc;             
    lc = p->lchild;         //lc指向的*p左子树根结点
    p->lchild = lc->rchild; //rc的右子树挂接为*p的左子树
    lc->rchild = p; p = lc; //p指向新的结点
}

//对以*p为根的二叉排序树作左旋处理
void L_Rotate(BSTree &p) 
{
    BSTree rc;             
    rc = p->rchild;         //rc指向的*p右子树根结点
    p->rchild = rc->lchild; //rc的左子树挂接为*p的右子树
    rc->lchild = p; p = rc; //p指向新的结点
}

//对以指针T所指结点为根的二叉树作左平衡旋转处理
void LeftBalance(BSTree &T)
{
    BSTree lc,rd;
    lc = T->lchild;          //lc指向*T的左子树根结点
    switch(lc->bf)           //检查*T的左子树的平衡度,并作相应平衡处理
    {
    case LH:                 //新结点插入在*T的左孩子的左子树上,要作单右旋处理
        T->bf = lc->bf = EH;
        R_Rotate(T);  break;
    case RH:                 //新结点插入在*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;
        L_Rotate(T->lchild); //对*T的左子树作左旋平衡处理
        R_Rotate(T);         //对*T作右旋平衡处理
    }
}

//对以指针T所指结点为根的二叉树作右平衡旋转处理
void RightBalance(BSTree &T)
{
    BSTree rc,ld;
    rc = T->rchild;         //rc指向*T的左子树根结点
    switch(rc->bf)          //检查*T的右子树的平衡度,并作相应平衡处理
    {
    case RH:                //新结点插入在*T的右孩子的右子树上,要作单左旋处理
        T->bf = rc->bf =EH;
        L_Rotate(T); break;
    case LH:                //新结点插入在*T的右孩子的左子树上,要作双旋处理
        ld = rc->lchild;    //ld指向*T的右孩子的左子树根
        switch(ld->bf)      //修改*T及其右孩子的平衡因子
        {
        case LH: T->bf = EH; rc->bf = RH; break;
        case EH: T->bf = rc->bf =EH; break;
        case RH: T->bf = LH; rc->bf = EH; break;
        }
        ld->bf = EH;
        R_Rotate(T->rchild);//对*T的右子树作左旋平衡处理
        L_Rotate(T);        //对*T作左旋平衡处理
    }
}

//插入结点e,若T中存在和e相同关键字的结点,则插入一个数据元素为e的新结点,并返回1,否则返回0
bool InsertAVL(BSTree &T,int e,bool &taller)
{
    if(!T)//插入新结点,树“长高”,置taller为true
    {
        T = (BSTree)malloc(sizeof(BSTNode)); 
        T->data = e;
        T->lchild = T->rchild =NULL;
        T->bf = EH; taller = true;
    }
    else
    {
        if(EQ(e,T->data))                 //树中已存在和有相同关键字的结点
        { taller = false;printf("已存在相同关键字的结点\n"); return 0; }//则不再插入
        if(LT(e,T->data))                 //应继续在*T的左子树中进行搜索
        {
            if(!InsertAVL(T->lchild,e,taller)) return 0;//未插入
            if(taller)                    //已插入到*T的左子树中且左子树“长高”
                switch(T->bf)             //检查*T的平衡度
         {
                  case LH:                //原本左子树比右子树高,需要作左平衡处理
                      LeftBalance(T); taller = false; break;
                  case EH:                //原本左子树、右子等高,现因左子树增高而使树增高
                      T->bf = LH; taller = true; break;
                  case RH:                //原本右子树比左子树高,现左、右子树等高
                      T->bf = EH; taller = false; break;
            }//switch(T->bf)
        }//if
        else                              //应继续在*T的右子树中进行搜索
        {
            if(!InsertAVL(T->rchild,e,taller)) return 0;//未插入
            if(taller)                    //已插入到*T的右子树中且右子树“长高”
                switch(T->bf)             //检查*T的平衡度
         {
                   case LH:               //原本左子树比右子树高,现左、右子树等高
                       T->bf = EH; taller = false; break;
                   case EH:               //原本左子树、右子等高,现因右子树增高而使树增高
                       T->bf = RH; taller = true; break;
                   case RH:               //原本右子树比左子树高,需要作右平衡处理
                       RightBalance(T); taller = false; break;
            }//switch(T->bf)
        }//else
    }//else
    return 1;
}//InsertAVL

//查找元素key是否在树T中
bool SearchBST(BSTree &T,int key)
{
    if(!T) return false;
    else if(EQ(key,T->data)) return true;
    else if(LT(key,T->data)) return SearchBST(T->lchild,key);
    else return SearchBST(T->rchild,key);
}

//按树状打印输出二叉树的元素,m表示结点所在层次,初次调用时m=o
void PrintBST(BSTree T,int m)
{
    int i;
    if(T->rchild) PrintBST(T->rchild,m+1);
    for(i = 1; i<=m; i++)  
        printf("     ");//打印 i 个空格以表示出层次
    printf("%d\n",T->data);//打印 T 元素,换行 
    if(T->lchild) 
        PrintBST(T->lchild,m+1);
   
}

//创建平衡二叉树,(注意:以输入-1为二叉树建立的结束)
void CreatBST(BSTree &T)
{
    int e,m;
    bool taller=false;
    T = NULL;
    printf("\n请输入关键字(以-1结束建立平衡二叉树):");
    scanf("%d",&e);getchar();
    while(e != -1)
    {
        InsertAVL(T,e,taller);
        printf("\n请输入关键字(以-1结束建立平衡二叉树):");
        scanf("%d",&e);getchar();taller=false;
    }
    m=0;
    printf("平衡二叉树创建结束,横向打印出树状结构:\n");
    if(T)  PrintBST(T,m);
    else  printf("这是一棵空树.\n");
}

//删除结点时左平衡旋转处理
void LeftBalance_div(BSTree &p,int &shorter)
{
 BSTree  p1,p2;
 if(p->bf==1) //p结点的左子树高,删除结点后p的bf减1,树变矮
 { p->bf=0; shorter=1; }
 else if(p->bf==0)//p结点左、右子树等高,删除结点后p的bf减1,树高不变
 { p->bf=-1; shorter=0; }
 else  //p结点的右子树高
 {
  p1=p->rchild;//p1指向p的右子树
  if(p1->bf==0)//p1结点左、右子树等高,删除结点后p的bf为-2,进行左旋处理,树高不变
  {
   L_Rotate(p);
   p1->bf=1; p->bf=-1; shorter=0;
        }
  else if(p1->bf==-1)//p1的右子树高,左旋处理后,树变矮
        {
   L_Rotate(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; shorter=1;
  }
  }

}

//删除结点时右平衡旋转处理
void RightBalance_div(BSTree &p,int &shorter)
{
 BSTree  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)
        {
   R_Rotate(p);
            p1->bf=-1; p->bf=1; shorter=0;
  }
        else if(p1->bf==1)
        {
   R_Rotate(p);
            p1->bf=p->bf=0; shorter=1;
        }
        else
        {
            p2=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(BSTree q,BSTree  &r,int &shorter)
{
 if(r->rchild==NULL)
    {
  q->data=r->data; q=r;
        r=r->lchild; free(q);
        shorter=1;
 }
    else 
    { 
  Delete(q,r->rchild,shorter);
        if(shorter==1) 
   RightBalance_div(r,shorter);
 }
}

//平衡二叉树的删除操作
int DeleteAVL(BSTree &p,int x,int &shorter)
{
 int k;
    BSTree q;
    if(p==NULL)  { printf("不存在要删除的关键字!!\n"); return 0;}
    else if(x<p->data)//在p的左子树中进行删除
    { 
  k=DeleteAVL(p->lchild,x,shorter);
        if(shorter==1)
   LeftBalance_div(p,shorter);
  return k;
 }
 else if(x>p->data)//在p的右子树中进行删除
    {
  k=DeleteAVL(p->rchild,x,shorter);
  if(shorter==1)
   RightBalance_div(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//左右子树均不空
        {
   Delete(q,q->lchild,shorter);
   if(shorter==1)
    LeftBalance_div(p,shorter);
   p=q; 
  }
       return 1;
 }
}

平衡二叉树算法实现 c语言版 插入 删除的更多相关文章

  1. 排序算法总结(C语言版)

    排序算法总结(C语言版) 1.    插入排序 1.1     直接插入排序 1.2     Shell排序 2.    交换排序 2.1     冒泡排序 2.2     快速排序 3.    选择 ...

  2. 最短路径-----迪杰斯特拉算法(C语言版)

    原文:http://blog.csdn.net/mu399/article/details/50903876 转两张思路图非常好:   描述略   图片思路很清晰.  Dijkstra不适用负权值,负 ...

  3. [算法] 常见排序算法总结(C语言版)

    常见排序算法总结 本文对比较常用且比较高效的排序算法进行了总结和解析,并贴出了比较精简的实现代码,包括选择排序.插入排序.归并排序.希尔排序.快速排序等.算法性能比较如下图所示: 1 冒泡排序 基本原 ...

  4. 和我一起从0学算法(C语言版)(一)

    第一章 排序 第一节 简化版桶排法 友情提示:此文章分享给所有小白,大牛请绕路! 生活中很多地方需要使用排序,价格的由低到高.距离的由远及近等,都是排序问题的体现.如果排序量较少,依靠个人能力很容易实 ...

  5. 7、滑动窗口套路算法框架——Go语言版

    前情提示:Go语言学习者.本文参考https://labuladong.gitee.io/algo,代码自己参考抒写,若有不妥之处,感谢指正 关于golang算法文章,为了便于下载和整理,都已开源放在 ...

  6. 和我一起从0学算法(C语言版)(四)

    第三章 搜索 深度优先搜索与宽度优先搜索 定义 深度优先搜索(DFS) 过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次. 宽度优先搜索(BFS) 不考虑结果的可能位 ...

  7. 和我一起从0学算法(C语言版)(三)

    第二章 暴力求解(枚举法) 第一节 小学奥数题-程序求解 观察下面的加法算式:       祥 瑞 生 辉   +   三 羊 献 瑞 -------------------    三 羊 生 瑞 气 ...

  8. 和我一起从0学算法(C语言版)(二)

    第一章 排序 第三节 快速排序 快速排序是最常用的排序方法.快排运用的递归方法很有意思.掌握了这种排序方法可以在将来学习递归时更快入门.只是快排的思路与之前的排序方法相比较为复杂,再加担心上我的表达能 ...

  9. 红黑树的删除详解与思路分析——不同于教科书上的算法(dart语言实现)

    对于红黑树的删除,看了数据结构的书,也看了很多网上的讲解和实现,但都不满意.很多讲解都是囫囵吞枣,知其然,不知其所以然,讲的晦涩难懂. 红黑树是平衡二叉树的一种,其删除算法是比较复杂的,因为删除后还要 ...

随机推荐

  1. C++ enum 作用域问题和解决方案

    C++ 中的枚举类型继承于 C 语言.就像其他从 C 语言继承过来的很多特性一样,C++ 枚举也有缺点,这其中最显著的莫过于作用域问题--在枚举类型中定义的常量,属于定义枚举的作用域,而不属于这个枚举 ...

  2. HDU 1584 蜘蛛牌

    题解:纸牌只能移到比其大一的纸牌上,所以移动方向是定的,那么,就只有选择移动先后的问题了,对于决定要移的纸牌,比如1,如果2,3,4都是visited的状态,那么1一定是要移动到5的,因为2,3,4一 ...

  3. 笔试题引出float数据的存储方式的深究

    笔试题: #include <iostream>#include <stdio.h>#include <string.h>#include <conio.h& ...

  4. javascript中处理引号编码&#034;

    1. <c:out value='${jxOrgJsonStr}' escapeXml="false"/> 2.或者使用innerText 直接接受${jxOrgJso ...

  5. Effective C++ 条款39

    我从本条款中学到了下面内容: 1.private继承不同于另外两种继承,派生类对象不能隐式转换为基类对象. 例如以下代码: class Bird//鸟 { }; class ostrich:priva ...

  6. c 整数的逆序输出 输入3,2就算 2+22+222的结果

    #include<stdio.h> #include<math.h> //整数逆序输出 void nixu() { int num,i; i = ; scanf("% ...

  7. JavaScript 高级程序设计(第3版)笔记——chapter7:函数表达式

    一.函数表达式的语法形式 匿名函数 var functionName = function(arg0, arg1, arg2) { //函数体 } 二.函数表达式没有函数提升 var a = 1; i ...

  8. openstack第1天

    入门openstack题外篇 老实说,我在写这篇文章的时候,对云的了解还是比较模糊的,也许是刚接触,不管怎样 总得写点什么,写完之后也许数月之后,感觉写的不是那么好,到时候在做修该吧! 今天我们就提一 ...

  9. UIWebvView 解决onClick 延迟相应问题

    在使用 UIWebView 的过程中, 发现 onClick 触发需要等待300-500ms, Google了一下, 发现是因为ScrollView 在等待doubleTap, 所以有延迟 使用如下代 ...

  10. codeforces 620E. New Year Tree dfs序+线段树+bitset

    题目链接 给一棵树, 每个节点有颜色, 两种操作, 一种是将一个节点的子树全都染色成c, 一种是查询一个节点的子树有多少个不同的颜色, c<=60. 每个节点一个bitset维护就可以. #in ...