平衡二叉排序树的各种算法

最近在写这学期学的数据结构综合性实验,本来整个程序在一周前就写出来了,可是由于其他原因,还没来得及写实验报告,昨晚跟今天一整个下午一直在写报告,发现其中很多漏洞,,,一个是插入新节点后旋转子树中写漏了一点,,因为自己测试了几组数据,发现居然运行不了,也是醉了,然后改了回来,然后通过好久,终于把实验报告写完了;下面是我写的整个程序,部分参考书上代码,如有错误,忘指出。

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define TRUE 1
#define FALSE 0
#define OK  1
#define ERROR  0
#define INFEASIBLE -1
#define OVERFLOW -2
#define STACK_INIT_SIZE 100 // 存储空间初始分配量
#define STACKINCREMENT 10 // 存储空间分配增量
#define MAXQsize 100 //队列空间初始化分配量
#define LH +1  //左边高
#define RH -1  //右边高
#define EH  0  //等高
bool taller ; //树是否长高
typedef int ElemType;
typedef int  Status;
int flag=0;//查找的标记
int l=0; //左子树的深度
int r=0; //有子树的深度
int jiedian=0; //树的节点数
typedef int ElemType;
typedef struct BiTNode
{
    ElemType data;
    int bf;  //平衡因子
    int out;  //后序遍历的非递归算法的标记(是否访问过)
    struct BiTNode *lchild,*rchild;//左右孩子指针
} BiTNode,*BiTree;  //树的结构


struct SqStack  //顺序栈
{
    BiTree *base; // 在栈构造之前和销毁之后,base的值为NULL
    BiTree *top; // 栈顶指针
    int stacksize; // 当前已分配的存储空间,以元素为单位
};


struct Queue  // 顺序队列
{
    BiTree base[MAXQsize];
    int front; // 对头指针
    int rear;  // 队尾指针指针
};
void R_Rotate(BiTree &p)
{
    //对以p为根的二叉排序树做右旋转处理,处理之后,p指向新的树根节点,
    //即选择处理之前的左子树根节点。
    BiTree lc;
    lc = (BiTree)malloc(sizeof(BiTNode));
    lc = p->lchild;
    p->lchild = lc->rchild;
    lc->rchild = p;
    p =lc;
}
void L_Rotate(BiTree &p)
{
    //对以p为根的二叉排序树做左旋转处理,处理之后,p指向新的树根节点,
    //即选择处理之前的右子树根节点。
    BiTree lc;
    lc = (BiTree)malloc(sizeof(BiTNode));
    lc = p->rchild;
    p->rchild = lc->lchild ;
    lc->lchild = p;
    p =lc;
}
void LeftBalance(BiTree &T)
{
    //对以指针T所指节点为根的二叉排序树左左平衡旋转处理,本算法结束时,
    //指针T指向新的根节点。
    BiTree lc,rd;
    lc = rd =(BiTree)malloc(sizeof(BiTNode));
    lc = T->lchild;
    switch(lc->bf)
    {
    case LH:
        T->bf = lc->bf = EH;
        R_Rotate(T);
        break;
    case RH:
        rd = lc->rchild;
        switch(rd->bf)
        {
        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);
        R_Rotate(T);
    }
}
void RightBalance(BiTree &T)
{
BiTree R,Rl;
R=(T)->rchild; /*  R指向T的右子树根结点 */
switch(R->bf)
{ /*  检查T的右子树的平衡度,并作相应平衡处理 */
case RH: /*  新结点插入在T的右孩子的右子树上,要作单左旋处理 */
 (T)->bf=R->bf=EH;
 L_Rotate(T);
 break;
case LH: /*  新结点插入在T的右孩子的左子树上,要作双旋处理 */
 Rl=R->lchild; /*  Rl指向T的右孩子的左子树根 */
 switch(Rl->bf)
 { /*  修改T及其右孩子的平衡因子 */
case RH: (T)->bf=LH;
R->bf=EH;
break;
case EH: (T)->bf=R->bf=EH;
break;
case LH: (T)->bf=EH;
R->bf=RH;
break;
 }
 Rl->bf=EH;
 R_Rotate((T)->rchild); /*  对T的右子树作右旋平衡处理 */
 L_Rotate(T); /*  对T作左旋平衡处理 */
}
}


Status InsertAVL(BiTree &T,int e,bool &taller)
{
    //若二叉排序树中不存在e相同的值,则插入,并且返回1;否则返回0;
    //taller 反应树长高与否。
    if(!T)
    {
        T = (BiTree)malloc(sizeof(BiTNode));
        T->data =e;
        T->out = 0;
        T->lchild = T->rchild =NULL;
        T->bf =EH;
        taller =TRUE;
    }
    else
    {
        if(e==T->data)//树中已存在和e有相同关键字的节点。
        {
            taller = FALSE;    //则不再插入
            return 0;
        }
        if(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;
                }
        }
        else
        {
            if(!InsertAVL(T->rchild,e,taller))return 0;//应在T的右子树中搜索
            if(taller)  //类似上面代码
                switch (T->bf)
                {
                case LH:
                    T->bf = EH;
                    taller =FALSE;
                    break;
                case EH:
                    T->bf = LH;
                    taller = TRUE;
                    break;
                case RH:
                    RightBalance(T);
                    taller =FALSE;
                    break;
                }
        }
    }
    return 1;
}


Status InitQueue(Queue &Q)//初始化队列
{
    Q.front=0;
    Q.rear=0;
    return OK;
}
Status InitStack(SqStack &S)//初始化栈
{
// 构造一个空栈S,该栈预定义大小为STACK_INIT_SIZE
    S.base=(BiTree*)malloc(STACK_INIT_SIZE*sizeof(BiTree));
    if(!S.base) return ERROR;
    S.top=S.base;
    S.stacksize=STACK_INIT_SIZE;
    return OK;
}


Status Enqueue(Queue &Q,BiTree T){
    //如果入队列没有满,则T入队


    if(Q.rear==MAXQsize)return ERROR;


    if(T)Q.base[Q.rear++]=T;


    return OK;
}
Status Delqueue(Queue &Q){
    //如果队列Q不为空,则输出对头数据,左右子树入队,对头出队。
    if(Q.front==Q.rear)return ERROR;
    else
    {
        printf("%d ",Q.base[Q.front]->data);
        Enqueue(Q,Q.base[Q.front]->lchild);//入队左子树
        Enqueue(Q,Q.base[Q.front]->rchild);//入队右子树
        Q.front++;
    }
    return OK;
}
Status QueueEmpty(Queue Q){
    //判断队列是否为空是返回1,否则返回0;
    if(Q.front==Q.rear)return OK;
    else return ERROR;
}


Status StackEmpty(SqStack S){
    //判断队列是否为空是返回1,否则返回0;
    if(S.top==S.base)return OK;
    else return ERROR;
}


Status Push(SqStack &S,BiTree e)//入栈
{
// 在栈S中插入元素e为新的栈顶元素
    *S.top++=e;
    return OK;
}


Status Pop(SqStack &S,BiTree &e)//出栈
{
// 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
    if(S.top==S.base) return ERROR;
    e=*(--S.top);
    return OK;
}
BiTree Getop(SqStack &S)//返回栈顶元素
{
// 若栈不空,则返回S的栈顶元素;否则返回NULL;
    if(S.top==S.base) return NULL;
    return *(S.top-1);
}
Status SearchBST(BiTree T,int key,BiTree f,BiTree &p)//搜索
{
    // 构造在T中查找key,用p指向它,如果找不到,p指向最后一个查找位置。
    if(!T)
    {
        p=f;
        return FALSE;
    }
    else if(key==T->data)
    {
        p=T;
        return true;
    }
    else if(key<T->data)
    {
        return SearchBST(T->lchild,key,T,p);
    }
    else return SearchBST(T->rchild,key,T,p);


} // CreateBiTree
Status Search(BiTree T,int key)//查找
{
    if(!T)
    {
        return true;
    }
    else if(key==T->data)
    {
        flag=1;
        return true;
    }
    else if(key<T->data)
    {
        return Search(T->lchild,key);
    }
    else return Search(T->rchild,key);


}
Status Visit( ElemType e )    // 输出元素e的值
{
    printf("%d ", e );
    return OK;
}// PrintElement
Status PreOrderTraverse2(BiTree T){
    //前序遍历二叉排序树(非递归),利用栈的先入后出的特点
    //对于每个元素,先访问他的数据,然后在进栈,访问左孩子,进栈,直到左孩子为空,出栈,
    //访问栈顶元素的有孩子。
    SqStack S;
    BiTree p;
    p=(BiTree)malloc(sizeof(BiTNode));
    InitStack(S);
    p=T;
    while(p||!StackEmpty(S))
    {
        if(p)
        {
            Visit(p->data);
            Push(S,p);
            p=p->lchild;
        }
        else
        {
            p = Getop(S);
            Pop(S,p);
            p=p->rchild;
        }
    }
    printf("\n");
    return OK;
}
Status InOrderTraverse2(BiTree T){
    //中序遍历二叉排序树(非递归)
    //对于每个元素,先进栈,直到左孩子为空,出栈,访问栈顶元素的数据。
    SqStack S;
    BiTree p;
    p=(BiTree)malloc(sizeof(BiTNode));
    InitStack(S);
    p=T;
    while(p||!StackEmpty(S))
    {
        if(p)
        {
            Push(S,p);
            p=p->lchild;
        }
        else
        {
            Pop(S,p);
            if(!Visit(p->data))return ERROR;
            p=p->rchild;
        }
    }
    printf("\n");
    return OK;
}
Status PostOrderTraverse2(BiTree T){
    //后序遍历二叉排序树(非递归)
    //这里用out做了一个标记
    //判断是否访问过
    SqStack S;
    BiTree p;
    p=(BiTree)malloc(sizeof(BiTNode));
    InitStack(S);
    p=T;
    while(p||!StackEmpty(S))
    {
        if(p&&!p->out)
        {
            Push(S,p);
            p=p->lchild;
        }
        else
        {
            p = Getop(S);
            if(p->out)
            {
                Visit(p->data);
                Pop(S,p);
                p=NULL;
            }
            else
            {
                p->out=1;
                p=p->rchild;
            }
        }
    }
    printf("\n");
    return OK;
}


Status PreOrderTraverse( BiTree T ){
    //前序遍历二叉排序树
    // 前序遍历二叉排序树T的递归算法,对每个数据元素调用函数Visit。
    if(T)
    {


        if(Visit(T->data))
        {
            if(PreOrderTraverse(T->lchild))
            {
                if(PreOrderTraverse(T->rchild))
                    return OK;
                else return ERROR;
            }
            else return ERROR;
        }
        else return ERROR;


    }
    else return OK;


} // PreOrderTraverse


Status InOrderTraverse( BiTree T ){
    //中序遍历二叉排序树
    // 中序遍历二叉排序树T的递归算法,对每个数据元素调用函数Visit。
    if(T)
    {


        if(InOrderTraverse(T->lchild))
            if(Visit(T->data))
                if(InOrderTraverse(T->rchild))
                    return OK;
        return ERROR;


    }
    else return OK;


} // InOrderTraverse


Status PostOrderTraverse( BiTree T ){
    //后序遍历二叉排序树
    // 后序遍历二叉排序树T的递归算法,对每个数据元素调用函数Visit。
    if(T)
    {


        if(PostOrderTraverse(T->lchild))
            if(PostOrderTraverse(T->rchild))
                if(Visit(T->data))
                    return OK;
        return ERROR;


    }
    else return OK;
} // PostOrderTraverse
Status Delete(BiTree & p)  {
    //删除节点
    //从二叉排序树中删除节点p,并重新连接它的左或右子树
    BiTree q,s;
    q = s = (BiTree)malloc(sizeof(BiTNode));
    if(!p->rchild) //右子树空则只需重新接它的左子树
    {
        q = p;
        p = p->lchild;
        free(q);
    }
    else if(!p->lchild)  //只需重新接它的右子树
    {
        q = p;
        p = p->rchild;
        free(q);
    }
    else
    {
        q = p;
        s = p->lchild;
        while(s->rchild)
        {
            q = s;
            s = s->rchild;
        }
        p->data = s->data;
        if(q!=p)q->rchild = s->lchild;
        else q->lchild = s->lchild;
        free(s);
    }
    return TRUE;
}
Status DeleteBST(BiTree &T,int key) {
    //删除关键字
    //若二叉排序树中存在于关键字Key相等的数据元素,则删除它并返回TRUE;否则返回FALSE
    if(!T)return FALSE;
    else
    {
        if(key==T->data)return Delete(T);
        else if(key<T->data)return DeleteBST(T->lchild,key);
        else return DeleteBST(T->rchild,key);
    }
}
//Funtion One
void InitBitree(BiTree &T)  //初始化二叉排序树
{
    int i,n,a;
    T=NULL;
    scanf("%d",&n);
    for(i=1; i<=n; i++)
    {
        scanf("%d",&a);
        InsertAVL(T,a,taller);
    }


}
//Funtion Two
void PreAndInAndPost_OrderTraverse(BiTree &T) {
    //函数封装
    //前中后遍历二叉排序树(递归)
    printf("以下三行为递归遍历结果。\n");
    PreOrderTraverse(T);
    printf("\n");
    InOrderTraverse(T);
    printf("\n");
    PostOrderTraverse(T);
    printf("\n");
}
//Funtion Three
void SearchInBitree(BiTree &T)
{
    //在树中查找关键字
    //这里使用while(1)来不断查找,当输入不为Y时,退出查找
    getchar();
    int c;
    char ch;
    while(1)
    {
        printf("输入Y表示继续查找,否则退出查找。\n输出1表示找到,0表示找不到!\n");
        scanf("%ch",&ch);
        if(ch!='Y')break;
        getchar();
        if(ch=='Y')
        {
            scanf("%d",&c);
            Search(T,c);//查找元素
            printf("%d\n",flag);
            if(flag==1)flag=0;
            getchar();
        }
    }
}
//Funtion Four
void InsertOne(BiTree &T)
{
    //插入一个新的元素
    int t;
    printf("请输入需要插入的元素。回车结束。\n");
    scanf("%d",&t);
    InsertAVL(T,t,taller);//调整结构
}
//Funtion Five
void PreAndInAndPost_OrderTraverse2(BiTree &T){
    //函数封装,把三个非递归遍历函数给封装到一个函数里
    printf("以下三行为非递归遍历结果。\n");
    PreOrderTraverse2(T);//前序遍历二叉排序树(非递归)
    InOrderTraverse2(T);//中序遍历二叉排序树(非递归)
    PostOrderTraverse2(T);//后序遍历二叉排序树(非递归)
}
//Funtion Six
void Cengcibianli(BiTree &T)
{
    //见名知意(233)层次遍历二叉排序树
    printf("以下为层次遍历结果。\n");
    Queue Q;
    InitQueue(Q);
    if(T)Enqueue(Q,T);
    while(!QueueEmpty(Q))
    {
        Delqueue(Q);
    }
    printf("\n");
}
//Funtion Seven
Status Swap( BiTree T ){
    //交换二叉排序树的左右结点,递归
    if(T)
    {


        BiTree temp;
        temp=T->lchild;
        T->lchild=T->rchild;
        T->rchild=temp;


        Swap(T->lchild);
        Swap(T->rchild);
    }
    return OK;
}
//Funtion Eight
Status Qiushendu( BiTree T )  {
    //求树的深度,递归
    if(!T)return 0;
    else
    {
        int l,r;
        l=Qiushendu(T->lchild);
        r=Qiushendu(T->rchild);
        return r>l?r+1:l+1;
    }
    return OK;
}
//Funtion Nine
Status Qiujiedian( BiTree T )  {
    //求树的节点数,这里定义了一个全局变量,直接记录节点数
    if(T){if((T->lchild==NULL)&&(T->rchild==NULL))jiedian++;
        else
        {
            Qiujiedian(T->lchild);
            Qiujiedian(T->rchild);
        }
    }
    return OK;
}
//Funtion Ten
void DeleteOne(BiTree &T)
{
    //删除一个数据元素
    int del;
    printf("请输入要删除的数据:");
    scanf("%d",&del);
    DeleteBST(T,del);
    printf("删除后的前序遍历:\n");
    PreOrderTraverse(T);
}
int main()
{
    BiTree T ;
    InitBitree(T);                                              //Funtion One
    PreAndInAndPost_OrderTraverse(T);                          //Funtion Two
    SearchInBitree(T);                                        //Funtion Three
    InsertOne(T);                                            //Funtion Four
    PreAndInAndPost_OrderTraverse(T);                       //Funtion Two
    PreAndInAndPost_OrderTraverse2(T);                     //Funtion Five
    Cengcibianli(T);                                      //Funtion Six
    Swap(T);                                             //Funtion Seven
    printf("前中后遍历交换后的二叉排序树\n");
    PreAndInAndPost_OrderTraverse(T);                  //Funtion Two
    Swap(T);                                          //Funtion Seven
    printf("前中后遍历再次交换后的二叉排序树\n");
    PreAndInAndPost_OrderTraverse(T);               //Funtion Two
    printf("此棵树的深度为:%d\n",Qiushendu(T));   //Funtion Eight
    Qiujiedian(T);                                //Funtion Nine
    printf("此棵树的叶子节点数为:%d\n",jiedian);
    DeleteOne(T);                               //Funtion Ten
    return 0;
}
/*example:
5
7 4 9 5 8
5
6
2
*/                  

by:guin_guo

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
描述 用函数实现如下二叉排序树算法: (1) 插入新结点 (2) 前序、中序、后序遍历二叉树 (3) 中序遍历的非递归算法 (4) 层次遍历二叉树 (5) 在二叉树中查找给定关键字(函数返回值为成功1,失败0) (6) 交换各结点的左右子树 (7) 求二叉树的深度 (8) 叶子结点数 Input 第一行:准备建树的结点个数n 第二行:输入n个整数,用空格分隔 第三行:输入待查找的关键字 第四行:输入待查找的关键字 第五行:输入待插入的关键字 Output 第一行:二叉树的先序遍历序列 第二行:二叉树的中序遍历序列 第三行:二叉树的后序遍历序列 第四行:查找结果 第五行:查找结果 第六行~第八行:插入新结点后的二叉树的先、中、序遍历序列 第九行:插入新结点后的二叉树的中序遍历序列(非递归算法) 第十行:插入新结点后的二叉树的层次遍历序列 第十一行~第十三行:第一次交换各结点的左右子树后的先、中、后序遍历序列 第十四行~第十六行:第二次交换各结点的左右子树后的先、中、后序遍历序列 第十七行:二叉树的深度 第十八行:叶子结点数 Sample Input 7 40 20 60 18 50 56 90 18 35 30 Sample Output 40 20 18 60 50 56 90 18 20 40 50 56 60 90 18 20 56 50 90 60 40 1 0 40 20 18 30 60 50 56 90 18 20 30 40 50 56 60 90 18 30 20 56 50 90 60 40 18 20 30 40 50 56 60 90 40 20 60 18 30 50 90 56 40 60 90 50 56 20 30 18 90 60 56 50 40 30 20 18 90 56 50 60 30 18 20 40 40 20 18 30 60 50 56 90 18 20 30 40 50 56 60 90 18 30 20 56 50 90 60 40 4 4

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值