zoukankan      html  css  js  c++  java
  • 二叉平衡排序树的基本操作

    //定义数据类型
     
    #define  MAXSIZE = 100;
    #define OK  1;
    #define ERROR 0;
     
    typedef int status;
    typedef int ElemType;
     
    //平衡二叉排序树的结构
    typedef struct Tnode
    {
    ElemType data;
    struct Tnode *lchild,*rchild;
    int height;          //以该节点为根的子树的高度
    }BBTnode,*BBTree;
     
    typedef BBTree Position;
    //栈定义
    typedef struct
    {
    BBTree *base,*top;    //栈指针成员
    int initsize;        //栈初始长度
    }Stack;
     
     
    //队列定义
    typedef struct
    {
    BBTree *front,*rear;  //队列指针成员
    int InitSize;        //栈初始长度
    }Queue;
    ----------------------------------------------------------------------------------
    插入和删除节点
     
    //插入节点函数
    status InsertBBT(BBTree &T,ElemType e)  //插入新结点
    {
    if(T == NULL)     //空树,建一个节点给树
    {
    T = (BBTree)malloc(sizeof(BBTnode));
    if(!T) return ERROR;
    T->data = e;
    T->lchild = T->rchild = NULL;
    T->height = 0;
    }
    else if(e < T->data)  //向左插入
    {
    InsertBBT(T->lchild,e);
    if(Height(T->lchild) - Height(T->rchild) == 2)  //出现不平衡了
    {
    //如果用序列(5,2,1...)就可会出现LL型,用序列(5,2,3...)就可会出现LR型
    if(e < T->lchild->data)  //这样对应于 LL 型
    T = LL_SingleRotate(T);
    else             //这个对应于 LR 型
    T = LR_DoubleRotate(T);
    }
    }
    else if(e > T->data)  //向右插入
    {
    InsertBBT(T->rchild,e);
    if(Height(T->rchild) - Height(T->lchild) == 2)  //出现不平衡了
    {
    //如果用序列(5,6,7...)就可会出现RR型,用序列(5,7,6...)就可会出现RL型
    if(e > T->rchild->data)  //这样对应于 RR 型
    T = RR_SingleRotate(T);
    else           //这样对应于 RL 型
    T = RL_DoubleRotate(T);
    }
    }
    //如果 e == T->data 的话什么也不干,最后要记录T->height
    T->height = Max(Height(T->lchild),Height(T->rchild)) + 1;
    return OK;
    }
     
    //删除节点函数
    status DeleteBBT(BBTree &T,ElemType e)             //删除某结点
    {
    Position temp;
     
    if(T == NULL) return ERROR;
    else if(e < T->data)
    return DeleteBBT(T->lchild,e);
    else if(e > T->data)
    return DeleteBBT(T->rchild,e);
    else   //即 e == T->data的情况
    {
    if(T->lchild != NULL && T->rchild !=NULL)    //有两个孩子
    {
    temp = FindMax(T->lchild);   //在右子树中找到最小的节点
    T->data = temp->data;  //用找到的最小节点的data代替要删除节点的data
    DeleteBBT(T->lchild,T->data);  //删除右边刚刚找出的最小的节点
    }
    else    //有一个或者没有孩子
    {
    temp = T;
    if(T->lchild == NULL)   //也处理了0个孩子的情况
    T = T->rchild;
    else if(T->rchild == NULL)
    T = T->lchild;
    free(temp);
    }
    return OK;
    }
    }
     
    //找最大的Element
    Position FindMax(BBTree T)          
    {
    if(T == NULL) return NULL;
    else if(T->rchild == NULL) return T;
    else return FindMax(T->rchild);
    }
     
    //求较大的数
    int Max(int l,int r)      
    {
    return l>r?l:r;
    }
     
     
    //求树的高度
    int Height(BBTree T)        
    {
    if(T == NULL) return -1;
    else return T->height;
    }
     
     //向左旋转一次,抓住k1(小的),让重力话事
    BBTree LL_SingleRotate(BBTree k2)   
    {
    BBTree k1;
    k1 = k2->lchild;
    k2->lchild = k1->rchild;
    k1->rchild = k2;
     
    k1->height = Max(Height(k1->lchild),k2->height) + 1;
    k2->height = Max(Height(k2->lchild),Height(k2->rchild)) +1;
    return k1;  //新的root
    }
     
     //向右旋转一次,抓住k2(大的),让重力话事
    BBTree RR_SingleRotate(BBTree k1)   
    {
    BBTree k2;
    k2 = k1->rchild;
    k1->rchild = k2->lchild;
    k2->lchild = k1;
     
    k1->height = Max(Height(k1->lchild),Height(k1->rchild)) +1;
    k2->height = Max(Height(k1->rchild),k1->height) + 1;
    return k2;  //新的root
    }
     
     //向左转一次,向右转一次
    BBTree LR_DoubleRotate(BBTree k3)   
    {
    k3->lchild = RR_SingleRotate(k3->lchild);  //先逆时针转
     
    return LL_SingleRotate(k3);               //再顺时针转
    }
     
    //向右转一次,向左转一次
    BBTree RL_DoubleRotate(BBTree k1)   
    {
    k1->rchild = LL_SingleRotate(k1->rchild);  //先顺时针转
     
    return RR_SingleRotate(k1);                //再逆时针转
     
    --------------------------------------------------------------------------------
     遍历
     
    //递归前序遍历
    status FirstViewRoot(BBTree T)       
    {
    if(T != NULL)
    {
    cout << T->data << " ";
    FirstViewRoot(T->lchild);
    FirstViewRoot(T->rchild);
    }
    return OK;
    }
     
    //递归中序遍历
    status MiddleViewRoot(BBTree T)      
    {
    if(T != NULL)
    {
    MiddleViewRoot(T->lchild);
    cout << T->data << " ";
    MiddleViewRoot(T->rchild);
    }
    return OK;
    }
     
     //递归后序遍历
    status LastViewRoot(BBTree T)      
    {
    if(T != NULL)
    {
    LastViewRoot(T->lchild);
    LastViewRoot(T->rchild);
    cout << T->data << " ";
    }
    return OK;
    }
     
     //非递归前序遍历
    status NonFirstView(BBTree T,Stack S)       
    {
    while(S.base != S.top || T != NULL)
    {
    while(T != NULL)        //向左走到最左
    {
    cout << T->data << " ";   //输出元素
    *S.top++ = T;
    T = T->lchild;
    }
    T=*--S.top;   //出栈
    T = T->rchild;      //转向右
    }
    return OK;
    }
     
     //非递归中序遍历
    status NonMiddleView(BBTree T,Stack S)      
    {
    while(S.base != S.top || T != NULL)
    {
    while(T != NULL)        //向左走到最左
    {
    *S.top++ = T;
    T = T->lchild;
    }
    T=*--S.top;   //出栈
    cout << T->data << " ";   //输出元素
    T = T->rchild;      //转向右
    }
    return OK;
    }
     
    //非递归后序遍历
    status NonLastView(BBTree T,Stack S)
    {
    BBTree pre = NULL;   //pre用来标记刚刚访问过的节点
    while(S.base != S.top || T != NULL)
    {
    while(T != NULL)        //向左走到最左
    {
    *S.top++ = T;
    T = T->lchild;
    }
    T=*(S.top - 1);   //取栈顶节点
    if(T->rchild == NULL || T->rchild == pre)  //如果T没有右孩子或者其右孩子刚刚被访问过
    {
    cout << T->data << " ";   //输出元素
    S.top--;      //已访问,令其出栈
    pre = T;     //标记为刚刚访问过了
    T = NULL;//这步是假设已经遍历完以这个节点为root的子树,如果栈空则真的完了,没有则没有完,会继续
    }
    else
    T = T->rchild;      //转向右
    }
    return OK;
    }
     
     //层次遍历
    status LevelView(BBTree T,Queue Q)         
    {
    if(T != NULL)
    {
    *Q.rear++ = T;
    while(Q.front != Q.rear)  //队列不空时
    {
    if(T->lchild != NULL) *Q.rear++ = T->lchild;  //左子树进队
    if(T->rchild != NULL) *Q.rear++ = T->rchild;  //右子树进队
    T = *Q.front++;       //出队
    cout << T->data << " ";
    T = *Q.front;         //最新的队头
    }
    }
    return OK;
    }
     
    ---------------------------------------------------------------------------
    在二叉树中查找给定关键字
     
    //(函数返回值为成功1,失败0)
    status FindKeyword(BBTree T,ElemType e) 
    {
    if(T!=NULL)
      {
    if(e == T->data) return OK;
    else if(e < T->data)  return FindKeyword(T->lchild,e);
    else  return FindKeyword(T->rchild,e);
      }
    else return ERROR;
    }
     
    -------------------------------------------------------------------------------
    交换各结点的左右子树
     
    status SwapSubtree(BBTree T) 
    {
    BBTree tmpNode;
    if(T != NULL)
    {
    tmpNode = T->lchild;
    T->lchild = T->rchild;
    T->rchild = tmpNode;
    SwapSubtree(T->lchild);
    SwapSubtree(T->rchild);
    }
    return OK;
    }
    -------------------------------------------------------------------------------
    求平衡二叉树的深度、节点总数,叶子节点数
     
     //求二叉树的深度
    int DeepOfTree(BBTree T)          
    {
    int deep,ldeep = 0,rdeep = 0;
    if(T != NULL)
    {
    ldeep = DeepOfTree(T->lchild);
    rdeep = DeepOfTree(T->rchild);
    deep = Max(ldeep,rdeep) + 1;
    }
    else return 0;
    return deep;
    }
     
      //总的结点数
    int TotalNodeNumber(BBTree T)            
    {
    int sum = 0,lsum = 0,rsum = 0;
    if(T != NULL)
    {
    lsum = TotalNodeNumber(T->lchild);
    rsum = TotalNodeNumber(T->rchild);
    sum = lsum + rsum + 1;
    return sum;
    }
    else return 0;
    }
     
    //叶子结点数
    int LeafNodeNumber(BBTree T)        
    {
    int cnt = 0,lcnt = 0,rcnt = 0;
    if(T != NULL)
    {
    if(T->lchild == NULL && T->rchild == NULL) cnt=1;
    else
    {
    lcnt = LeafNodeNumber(T->lchild);
    rcnt = LeafNodeNumber(T->rchild);
    cnt = lcnt + rcnt;
    }
    }
    else return 0;
    return cnt;
    }
  • 相关阅读:
    Android中Context样式分析
    Android组件化实践
    插着USB mic开机时,系统没有声音问题
    Android7.1 解决ttyUSB串口节点不固定问题
    android中设置里面版本号的显示
    android7.1添加开机启动服务被selinux禁用问题
    Settings中删除一些默认的选项
    es8323codec调节录播音量大小
    user版本串口不能输入
    高新兴GM510模块调试
  • 原文地址:https://www.cnblogs.com/yujon/p/5467613.html
Copyright © 2011-2022 走看看