第十四周 项目5 平衡二叉树 包括二叉树的删除和插入

来源:互联网 发布:淘宝宝贝描述技巧 编辑:程序博客网 时间:2024/05/03 06:54
//头文件 #ifndef GRAPH_H_INCLUDED#define GRAPH_H_INCLUDED#define MAXV 100                //最大顶点个数#define INF 32767       //INF表示∞typedef int InfoType;//以下定义邻接矩阵类型typedef struct{    int no;                     //顶点编号    InfoType info;              //顶点其他信息,在此存放带权图权值} VertexType;                   //顶点类型typedef struct                  //图的定义{    int edges[MAXV][MAXV];      //邻接矩阵    int n,e;                    //顶点数,弧数    VertexType vexs[MAXV];      //存放顶点信息} MGraph;                       //图的邻接矩阵类型//以下定义邻接表类型typedef struct ANode            //弧的结点结构类型{    int adjvex;                 //该弧的终点位置    struct ANode *nextarc;      //指向下一条弧的指针    InfoType info;              //该弧的相关信息,这里用于存放权值} ArcNode;typedef int Vertex;typedef struct Vnode            //邻接表头结点的类型{    Vertex data;                //顶点信息    int count;                  //存放顶点入度,只在拓扑排序中用    ArcNode *firstarc;          //指向第一条弧} VNode;typedef VNode AdjList[MAXV];    //AdjList是邻接表类型typedef struct{    AdjList adjlist;            //邻接表    int n,e;                    //图中顶点数n和边数e} ALGraph;                      //图的邻接表类型//功能:由一个反映图中顶点邻接关系的二维数组,构造出用邻接矩阵存储的图//参数:Arr - 数组名,由于形式参数为二维数组时必须给出每行的元素个数,在此将参数Arr声明为一维数组名(指向int的指针)//      n - 矩阵的阶数//      g - 要构造出来的邻接矩阵数据结构void ArrayToMat(int *Arr, int n, MGraph &g); //用普通数组构造图的邻接矩阵void ArrayToList(int *Arr, int n, ALGraph *&); //用普通数组构造图的邻接表void MatToList(MGraph g,ALGraph *&G);//将邻接矩阵g转换成邻接表Gvoid ListToMat(ALGraph *G,MGraph &g);//将邻接表G转换成邻接矩阵gvoid DispMat(MGraph g);//输出邻接矩阵gvoid DispAdj(ALGraph *G);//输出邻接表G#endif // GRAPH_H_INCLUDED#include <stdio.h>#include <malloc.h>//功能:由一个反映图中顶点邻接关系的二维数组,构造出用邻接矩阵存储的图//参数:Arr - 数组名,由于形式参数为二维数组时必须给出每行的元素个数,在此将参数Arr声明为一维数组名(指向int的指针)//      n - 矩阵的阶数//      g - 要构造出来的邻接矩阵数据结构void ArrayToMat(int *Arr, int n, MGraph &g){    int i,j,count=0;  //count用于统计边数,即矩阵中非0元素个数    g.n=n;    for (i=0; i<g.n; i++)        for (j=0; j<g.n; j++)        {            g.edges[i][j]=Arr[i*n+j]; //将Arr看作n×n的二维数组,Arr[i*n+j]即是Arr[i][j],计算存储位置的功夫在此应用            if(g.edges[i][j]!=0 && g.edges[i][j]!=INF)                count++;        }    g.e=count;}void ArrayToList(int *Arr, int n, ALGraph *&G){    int i,j,count=0;  //count用于统计边数,即矩阵中非0元素个数    ArcNode *p;    G=(ALGraph *)malloc(sizeof(ALGraph));    G->n=n;    for (i=0; i<n; i++)                 //给邻接表中所有头节点的指针域置初值        G->adjlist[i].firstarc=NULL;    for (i=0; i<n; i++)                 //检查邻接矩阵中每个元素        for (j=n-1; j>=0; j--)            if (Arr[i*n+j]!=0)      //存在一条边,将Arr看作n×n的二维数组,Arr[i*n+j]即是Arr[i][j]            {                p=(ArcNode *)malloc(sizeof(ArcNode));   //创建一个节点*p                p->adjvex=j;                p->info=Arr[i*n+j];                p->nextarc=G->adjlist[i].firstarc;      //采用头插法插入*p                G->adjlist[i].firstarc=p;            }    G->e=count;}void MatToList(MGraph g, ALGraph *&G)//将邻接矩阵g转换成邻接表G{    int i,j;    ArcNode *p;    G=(ALGraph *)malloc(sizeof(ALGraph));    for (i=0; i<g.n; i++)                   //给邻接表中所有头节点的指针域置初值        G->adjlist[i].firstarc=NULL;    for (i=0; i<g.n; i++)                   //检查邻接矩阵中每个元素        for (j=g.n-1; j>=0; j--)            if (g.edges[i][j]!=0)       //存在一条边            {                p=(ArcNode *)malloc(sizeof(ArcNode));   //创建一个节点*p                p->adjvex=j;                p->info=g.edges[i][j];                p->nextarc=G->adjlist[i].firstarc;      //采用头插法插入*p                G->adjlist[i].firstarc=p;            }    G->n=g.n;    G->e=g.e;}void ListToMat(ALGraph *G,MGraph &g)//将邻接表G转换成邻接矩阵g{    int i,j;    ArcNode *p;    g.n=G->n;   //根据一楼同学“举报”改的。g.n未赋值,下面的初始化不起作用    g.e=G->e;    for (i=0; i<g.n; i++)   //先初始化邻接矩阵        for (j=0; j<g.n; j++)            g.edges[i][j]=0;    for (i=0; i<G->n; i++)  //根据邻接表,为邻接矩阵赋值    {        p=G->adjlist[i].firstarc;        while (p!=NULL)        {            g.edges[i][p->adjvex]=p->info;            p=p->nextarc;        }    }}void DispMat(MGraph g)//输出邻接矩阵g{    int i,j;    for (i=0; i<g.n; i++)    {        for (j=0; j<g.n; j++)            if (g.edges[i][j]==INF)                printf("%3s","∞");            else                printf("%3d",g.edges[i][j]);        printf("\n");    }}void DispAdj(ALGraph *G)//输出邻接表G{    int i;    ArcNode *p;    for (i=0; i<G->n; i++)    {        p=G->adjlist[i].firstarc;        printf("%3d: ",i);        while (p!=NULL)        {            printf("-->%d/%d ",p->adjvex,p->info);            p=p->nextarc;        }        printf("\n");    }}#include <stdio.h>#include <malloc.h>typedef int KeyType;                    //定义关键字类型typedef struct node                     //记录类型{    KeyType key;                        //关键字项    int bf;                             //平衡因子    InfoType data;                      //其他数据域    struct node *lchild,*rchild;        //左右孩子指针} BSTNode;void LeftProcess(BSTNode *&p,int &taller)//对以指针p所指结点为根的二叉树作左平衡旋转处理,本算法结束时,指针p指向新的根结点{    BSTNode *p1,*p2;    if (p->bf==0)           //原本左、右子树等高,现因左子树增高而使树增高    {        p->bf=1;        taller=1;    }    else if (p->bf==-1)     //原本右子树比左子树高,现左、右子树等高    {        p->bf=0;        taller=0;    }    else                    //原本左子树比右子树高,需作左子树的平衡处理    {        p1=p->lchild;       //p指向*p的左子树根结点        if (p1->bf==1)      //新结点插入在*b的左孩子的左子树上,要作LL调整        {            p->lchild=p1->rchild;            p1->rchild=p;            p->bf=p1->bf=0;            p=p1;        }        else if (p1->bf==-1)    //新结点插入在*b的左孩子的右子树上,要作LR调整        {            p2=p1->rchild;            p1->rchild=p2->lchild;            p2->lchild=p1;            p->lchild=p2->rchild;            p2->rchild=p;            if (p2->bf==0)          //新结点插在*p2处作为叶子结点的情况                p->bf=p1->bf=0;            else if (p2->bf==1)     //新结点插在*p2的左子树上的情况            {                p1->bf=0;                p->bf=-1;            }            else                    //新结点插在*p2的右子树上的情况            {                p1->bf=1;                p->bf=0;            }            p=p2;            p->bf=0;            //仍将p指向新的根结点,并置其bf值为0        }        taller=0;    }}void RightProcess(BSTNode *&p,int &taller)//对以指针p所指结点为根的二叉树作右平衡旋转处理,本算法结束时,指针p指向新的根结点{    BSTNode *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;       //p指向*p的右子树根结点        if (p1->bf==-1)     //新结点插入在*b的右孩子的右子树上,要作RR调整        {            p->rchild=p1->lchild;            p1->lchild=p;            p->bf=p1->bf=0;            p=p1;        }        else if (p1->bf==1) //新结点插入在*p的右孩子的左子树上,要作RL调整        {            p2=p1->lchild;            p1->lchild=p2->rchild;            p2->rchild=p1;            p->rchild=p2->lchild;            p2->lchild=p;            if (p2->bf==0)          //新结点插在*p2处作为叶子结点的情况                p->bf=p1->bf=0;            else if (p2->bf==-1)    //新结点插在*p2的右子树上的情况            {                p1->bf=0;                p->bf=1;            }            else                    //新结点插在*p2的左子树上的情况            {                p1->bf=-1;                p->bf=0;            }            p=p2;            p->bf=0;            //仍将p指向新的根结点,并置其bf值为0        }        taller=0;    }}int InsertAVL(BSTNode *&b,KeyType e,int &taller)/*若在平衡的二叉排序树b中不存在和e有相同关键字的结点,则插入一个  数据元素为e的新结点,并返回1,否则返回0。若因插入而使二叉排序树  失去平衡,则作平衡旋转处理,布尔变量taller反映b长高与否*/{    if(b==NULL)         //原为空树,插入新结点,树“长高”,置taller为1    {        b=(BSTNode *)malloc(sizeof(BSTNode));        b->key=e;        b->lchild=b->rchild=NULL;        b->bf=0;        taller=1;    }    else    {        if (e==b->key)              //树中已存在和e有相同关键字的结点则不再插入        {            taller=0;            return 0;        }        if (e<b->key)               //应继续在*b的左子树中进行搜索        {            if ((InsertAVL(b->lchild,e,taller))==0) //未插入                return 0;            if (taller==1)          //已插入到*b的左子树中且左子树“长高”                LeftProcess(b,taller);        }        else                        //应继续在*b的右子树中进行搜索        {            if ((InsertAVL(b->rchild,e,taller))==0) //未插入                return 0;            if (taller==1)          //已插入到b的右子树且右子树“长高”                RightProcess(b,taller);        }    }    return 1;}void DispBSTree(BSTNode *b) //以括号表示法输出AVL{    if (b!=NULL)    {        printf("%d",b->key);        if (b->lchild!=NULL || b->rchild!=NULL)        {            printf("(");            DispBSTree(b->lchild);            if (b->rchild!=NULL) printf(",");            DispBSTree(b->rchild);            printf(")");        }    }}void LeftProcess1(BSTNode *&p,int &taller)  //在删除结点时进行左处理{    BSTNode *p1,*p2;    if (p->bf==1)    {        p->bf=0;        taller=1;    }    else if (p->bf==0)    {        p->bf=-1;        taller=0;    }    else        //p->bf=-1    {        p1=p->rchild;        if (p1->bf==0)          //需作RR调整        {            p->rchild=p1->lchild;            p1->lchild=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;            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;            taller=1;        }    }}void RightProcess1(BSTNode *&p,int &taller) //在删除结点时进行右处理{    BSTNode *p1,*p2;    if (p->bf==-1)    {        p->bf=0;        taller=-1;    }    else if (p->bf==0)    {        p->bf=1;        taller=0;    }    else        //p->bf=1    {        p1=p->lchild;        if (p1->bf==0)          //需作LL调整        {            p->lchild=p1->rchild;            p1->rchild=p;            p1->bf=-1;            p->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;            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;            taller=1;        }    }}void Delete2(BSTNode *q,BSTNode *&r,int &taller)//由DeleteAVL()调用,用于处理被删结点左右子树均不空的情况{    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)            RightProcess1(r,taller);    }}int DeleteAVL(BSTNode *&p,KeyType x,int &taller) //在AVL树p中删除关键字为x的结点{    int k;    BSTNode *q;    if (p==NULL)        return 0;    else if (x<p->key)    {        k=DeleteAVL(p->lchild,x,taller);        if (taller==1)            LeftProcess1(p,taller);        return k;    }    else if (x>p->key)    {        k=DeleteAVL(p->rchild,x,taller);        if (taller==1)            RightProcess1(p,taller);        return k;    }    else            //找到了关键字为x的结点,由p指向它    {        q=p;        if (p->rchild==NULL)        //被删结点右子树为空        {            p=p->lchild;            free(q);            taller=1;        }        else if (p->lchild==NULL)   //被删结点左子树为空        {            p=p->rchild;            free(q);            taller=1;        }        else                        //被删结点左右子树均不空        {            Delete2(q,q->lchild,taller);            if (taller==1)                LeftProcess1(q,taller);            p=q;        }        return 1;    }}int main(){    BSTNode *b=NULL;    int i,j,k;    KeyType a[]= {16,3,7,11,9,26,18,14,15},n=9; //例10.5    printf(" 创建一棵AVL树:\n");    for(i=0; i<n; i++)    {        printf("   第%d步,插入%d元素:",i+1,a[i]);        InsertAVL(b,a[i],j);        DispBSTree(b);        printf("\n");    }    printf("   AVL:");    DispBSTree(b);    printf("\n");    printf(" 删除结点:\n");                     //例10.6    k=11;    printf("   删除结点%d:",k);    DeleteAVL(b,k,j);    printf("   AVL:");    DispBSTree(b);    printf("\n");    k=9;    printf("   删除结点%d:",k);    DeleteAVL(b,k,j);    printf("   AVL:");    DispBSTree(b);    printf("\n");    k=15;    printf("   删除结点%d:",k);    DeleteAVL(b,k,j);    printf("   AVL:");    DispBSTree(b);    printf("\n\n");    return 0;}
//源文件#ifndef GRAPH_H_INCLUDED#define GRAPH_H_INCLUDED#define MAXV 100                //最大顶点个数#define INF 32767       //INF表示∞typedef int InfoType;//以下定义邻接矩阵类型typedef struct{    int no;                     //顶点编号    InfoType info;              //顶点其他信息,在此存放带权图权值} VertexType;                   //顶点类型typedef struct                  //图的定义{    int edges[MAXV][MAXV];      //邻接矩阵    int n,e;                    //顶点数,弧数    VertexType vexs[MAXV];      //存放顶点信息} MGraph;                       //图的邻接矩阵类型//以下定义邻接表类型typedef struct ANode            //弧的结点结构类型{    int adjvex;                 //该弧的终点位置    struct ANode *nextarc;      //指向下一条弧的指针    InfoType info;              //该弧的相关信息,这里用于存放权值} ArcNode;typedef int Vertex;typedef struct Vnode            //邻接表头结点的类型{    Vertex data;                //顶点信息    int count;                  //存放顶点入度,只在拓扑排序中用    ArcNode *firstarc;          //指向第一条弧} VNode;typedef VNode AdjList[MAXV];    //AdjList是邻接表类型typedef struct{    AdjList adjlist;            //邻接表    int n,e;                    //图中顶点数n和边数e} ALGraph;                      //图的邻接表类型//功能:由一个反映图中顶点邻接关系的二维数组,构造出用邻接矩阵存储的图//参数:Arr - 数组名,由于形式参数为二维数组时必须给出每行的元素个数,在此将参数Arr声明为一维数组名(指向int的指针)//      n - 矩阵的阶数//      g - 要构造出来的邻接矩阵数据结构void ArrayToMat(int *Arr, int n, MGraph &g); //用普通数组构造图的邻接矩阵void ArrayToList(int *Arr, int n, ALGraph *&); //用普通数组构造图的邻接表void MatToList(MGraph g,ALGraph *&G);//将邻接矩阵g转换成邻接表Gvoid ListToMat(ALGraph *G,MGraph &g);//将邻接表G转换成邻接矩阵gvoid DispMat(MGraph g);//输出邻接矩阵gvoid DispAdj(ALGraph *G);//输出邻接表G#endif // GRAPH_H_INCLUDED#include <stdio.h>#include <malloc.h>//功能:由一个反映图中顶点邻接关系的二维数组,构造出用邻接矩阵存储的图//参数:Arr - 数组名,由于形式参数为二维数组时必须给出每行的元素个数,在此将参数Arr声明为一维数组名(指向int的指针)//      n - 矩阵的阶数//      g - 要构造出来的邻接矩阵数据结构void ArrayToMat(int *Arr, int n, MGraph &g){    int i,j,count=0;  //count用于统计边数,即矩阵中非0元素个数    g.n=n;    for (i=0; i<g.n; i++)        for (j=0; j<g.n; j++)        {            g.edges[i][j]=Arr[i*n+j]; //将Arr看作n×n的二维数组,Arr[i*n+j]即是Arr[i][j],计算存储位置的功夫在此应用            if(g.edges[i][j]!=0 && g.edges[i][j]!=INF)                count++;        }    g.e=count;}void ArrayToList(int *Arr, int n, ALGraph *&G){    int i,j,count=0;  //count用于统计边数,即矩阵中非0元素个数    ArcNode *p;    G=(ALGraph *)malloc(sizeof(ALGraph));    G->n=n;    for (i=0; i<n; i++)                 //给邻接表中所有头节点的指针域置初值        G->adjlist[i].firstarc=NULL;    for (i=0; i<n; i++)                 //检查邻接矩阵中每个元素        for (j=n-1; j>=0; j--)            if (Arr[i*n+j]!=0)      //存在一条边,将Arr看作n×n的二维数组,Arr[i*n+j]即是Arr[i][j]            {                p=(ArcNode *)malloc(sizeof(ArcNode));   //创建一个节点*p                p->adjvex=j;                p->info=Arr[i*n+j];                p->nextarc=G->adjlist[i].firstarc;      //采用头插法插入*p                G->adjlist[i].firstarc=p;            }    G->e=count;}void MatToList(MGraph g, ALGraph *&G)//将邻接矩阵g转换成邻接表G{    int i,j;    ArcNode *p;    G=(ALGraph *)malloc(sizeof(ALGraph));    for (i=0; i<g.n; i++)                   //给邻接表中所有头节点的指针域置初值        G->adjlist[i].firstarc=NULL;    for (i=0; i<g.n; i++)                   //检查邻接矩阵中每个元素        for (j=g.n-1; j>=0; j--)            if (g.edges[i][j]!=0)       //存在一条边            {                p=(ArcNode *)malloc(sizeof(ArcNode));   //创建一个节点*p                p->adjvex=j;                p->info=g.edges[i][j];                p->nextarc=G->adjlist[i].firstarc;      //采用头插法插入*p                G->adjlist[i].firstarc=p;            }    G->n=g.n;    G->e=g.e;}void ListToMat(ALGraph *G,MGraph &g)//将邻接表G转换成邻接矩阵g{    int i,j;    ArcNode *p;    g.n=G->n;   //根据一楼同学“举报”改的。g.n未赋值,下面的初始化不起作用    g.e=G->e;    for (i=0; i<g.n; i++)   //先初始化邻接矩阵        for (j=0; j<g.n; j++)            g.edges[i][j]=0;    for (i=0; i<G->n; i++)  //根据邻接表,为邻接矩阵赋值    {        p=G->adjlist[i].firstarc;        while (p!=NULL)        {            g.edges[i][p->adjvex]=p->info;            p=p->nextarc;        }    }}void DispMat(MGraph g)//输出邻接矩阵g{    int i,j;    for (i=0; i<g.n; i++)    {        for (j=0; j<g.n; j++)            if (g.edges[i][j]==INF)                printf("%3s","∞");            else                printf("%3d",g.edges[i][j]);        printf("\n");    }}void DispAdj(ALGraph *G)//输出邻接表G{    int i;    ArcNode *p;    for (i=0; i<G->n; i++)    {        p=G->adjlist[i].firstarc;        printf("%3d: ",i);        while (p!=NULL)        {            printf("-->%d/%d ",p->adjvex,p->info);            p=p->nextarc;        }        printf("\n");    }}#include <stdio.h>#include <malloc.h>typedef int KeyType;                    //定义关键字类型typedef struct node                     //记录类型{    KeyType key;                        //关键字项    int bf;                             //平衡因子    InfoType data;                      //其他数据域    struct node *lchild,*rchild;        //左右孩子指针} BSTNode;void LeftProcess(BSTNode *&p,int &taller)//对以指针p所指结点为根的二叉树作左平衡旋转处理,本算法结束时,指针p指向新的根结点{    BSTNode *p1,*p2;    if (p->bf==0)           //原本左、右子树等高,现因左子树增高而使树增高    {        p->bf=1;        taller=1;    }    else if (p->bf==-1)     //原本右子树比左子树高,现左、右子树等高    {        p->bf=0;        taller=0;    }    else                    //原本左子树比右子树高,需作左子树的平衡处理    {        p1=p->lchild;       //p指向*p的左子树根结点        if (p1->bf==1)      //新结点插入在*b的左孩子的左子树上,要作LL调整        {            p->lchild=p1->rchild;            p1->rchild=p;            p->bf=p1->bf=0;            p=p1;        }        else if (p1->bf==-1)    //新结点插入在*b的左孩子的右子树上,要作LR调整        {            p2=p1->rchild;            p1->rchild=p2->lchild;            p2->lchild=p1;            p->lchild=p2->rchild;            p2->rchild=p;            if (p2->bf==0)          //新结点插在*p2处作为叶子结点的情况                p->bf=p1->bf=0;            else if (p2->bf==1)     //新结点插在*p2的左子树上的情况            {                p1->bf=0;                p->bf=-1;            }            else                    //新结点插在*p2的右子树上的情况            {                p1->bf=1;                p->bf=0;            }            p=p2;            p->bf=0;            //仍将p指向新的根结点,并置其bf值为0        }        taller=0;    }}void RightProcess(BSTNode *&p,int &taller)//对以指针p所指结点为根的二叉树作右平衡旋转处理,本算法结束时,指针p指向新的根结点{    BSTNode *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;       //p指向*p的右子树根结点        if (p1->bf==-1)     //新结点插入在*b的右孩子的右子树上,要作RR调整        {            p->rchild=p1->lchild;            p1->lchild=p;            p->bf=p1->bf=0;            p=p1;        }        else if (p1->bf==1) //新结点插入在*p的右孩子的左子树上,要作RL调整        {            p2=p1->lchild;            p1->lchild=p2->rchild;            p2->rchild=p1;            p->rchild=p2->lchild;            p2->lchild=p;            if (p2->bf==0)          //新结点插在*p2处作为叶子结点的情况                p->bf=p1->bf=0;            else if (p2->bf==-1)    //新结点插在*p2的右子树上的情况            {                p1->bf=0;                p->bf=1;            }            else                    //新结点插在*p2的左子树上的情况            {                p1->bf=-1;                p->bf=0;            }            p=p2;            p->bf=0;            //仍将p指向新的根结点,并置其bf值为0        }        taller=0;    }}int InsertAVL(BSTNode *&b,KeyType e,int &taller)/*若在平衡的二叉排序树b中不存在和e有相同关键字的结点,则插入一个  数据元素为e的新结点,并返回1,否则返回0。若因插入而使二叉排序树  失去平衡,则作平衡旋转处理,布尔变量taller反映b长高与否*/{    if(b==NULL)         //原为空树,插入新结点,树“长高”,置taller为1    {        b=(BSTNode *)malloc(sizeof(BSTNode));        b->key=e;        b->lchild=b->rchild=NULL;        b->bf=0;        taller=1;    }    else    {        if (e==b->key)              //树中已存在和e有相同关键字的结点则不再插入        {            taller=0;            return 0;        }        if (e<b->key)               //应继续在*b的左子树中进行搜索        {            if ((InsertAVL(b->lchild,e,taller))==0) //未插入                return 0;            if (taller==1)          //已插入到*b的左子树中且左子树“长高”                LeftProcess(b,taller);        }        else                        //应继续在*b的右子树中进行搜索        {            if ((InsertAVL(b->rchild,e,taller))==0) //未插入                return 0;            if (taller==1)          //已插入到b的右子树且右子树“长高”                RightProcess(b,taller);        }    }    return 1;}void DispBSTree(BSTNode *b) //以括号表示法输出AVL{    if (b!=NULL)    {        printf("%d",b->key);        if (b->lchild!=NULL || b->rchild!=NULL)        {            printf("(");            DispBSTree(b->lchild);            if (b->rchild!=NULL) printf(",");            DispBSTree(b->rchild);            printf(")");        }    }}void LeftProcess1(BSTNode *&p,int &taller)  //在删除结点时进行左处理{    BSTNode *p1,*p2;    if (p->bf==1)    {        p->bf=0;        taller=1;    }    else if (p->bf==0)    {        p->bf=-1;        taller=0;    }    else        //p->bf=-1    {        p1=p->rchild;        if (p1->bf==0)          //需作RR调整        {            p->rchild=p1->lchild;            p1->lchild=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;            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;            taller=1;        }    }}void RightProcess1(BSTNode *&p,int &taller) //在删除结点时进行右处理{    BSTNode *p1,*p2;    if (p->bf==-1)    {        p->bf=0;        taller=-1;    }    else if (p->bf==0)    {        p->bf=1;        taller=0;    }    else        //p->bf=1    {        p1=p->lchild;        if (p1->bf==0)          //需作LL调整        {            p->lchild=p1->rchild;            p1->rchild=p;            p1->bf=-1;            p->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;            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;            taller=1;        }    }}void Delete2(BSTNode *q,BSTNode *&r,int &taller)//由DeleteAVL()调用,用于处理被删结点左右子树均不空的情况{    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)            RightProcess1(r,taller);    }}int DeleteAVL(BSTNode *&p,KeyType x,int &taller) //在AVL树p中删除关键字为x的结点{    int k;    BSTNode *q;    if (p==NULL)        return 0;    else if (x<p->key)    {        k=DeleteAVL(p->lchild,x,taller);        if (taller==1)            LeftProcess1(p,taller);        return k;    }    else if (x>p->key)    {        k=DeleteAVL(p->rchild,x,taller);        if (taller==1)            RightProcess1(p,taller);        return k;    }    else            //找到了关键字为x的结点,由p指向它    {        q=p;        if (p->rchild==NULL)        //被删结点右子树为空        {            p=p->lchild;            free(q);            taller=1;        }        else if (p->lchild==NULL)   //被删结点左子树为空        {            p=p->rchild;            free(q);            taller=1;        }        else                        //被删结点左右子树均不空        {            Delete2(q,q->lchild,taller);            if (taller==1)                LeftProcess1(q,taller);            p=q;        }        return 1;    }}int main(){    BSTNode *b=NULL;    int i,j,k;    KeyType a[]= {16,3,7,11,9,26,18,14,15},n=9; //例10.5    printf(" 创建一棵AVL树:\n");    for(i=0; i<n; i++)    {        printf("   第%d步,插入%d元素:",i+1,a[i]);        InsertAVL(b,a[i],j);        DispBSTree(b);        printf("\n");    }    printf("   AVL:");    DispBSTree(b);    printf("\n");    printf(" 删除结点:\n");                     //例10.6    k=11;    printf("   删除结点%d:",k);    DeleteAVL(b,k,j);    printf("   AVL:");    DispBSTree(b);    printf("\n");    k=9;    printf("   删除结点%d:",k);    DeleteAVL(b,k,j);    printf("   AVL:");    DispBSTree(b);    printf("\n");    k=15;    printf("   删除结点%d:",k);    DeleteAVL(b,k,j);    printf("   AVL:");    DispBSTree(b);    printf("\n\n");    return 0;}

//主函数#include <stdio.h>#include <malloc.h>typedef int KeyType;                    //定义关键字类型typedef char InfoType;typedef struct node                     //记录类型{    KeyType key;                        //关键字项    int bf;                             //平衡因子    InfoType data;                      //其他数据域    struct node *lchild,*rchild;        //左右孩子指针} BSTNode;void LeftProcess(BSTNode *&p,int &taller)//对以指针p所指结点为根的二叉树作左平衡旋转处理,本算法结束时,指针p指向新的根结点{    BSTNode *p1,*p2;    if (p->bf==0)           //原本左、右子树等高,现因左子树增高而使树增高    {        p->bf=1;        taller=1;    }    else if (p->bf==-1)     //原本右子树比左子树高,现左、右子树等高    {        p->bf=0;        taller=0;    }    else                    //原本左子树比右子树高,需作左子树的平衡处理    {        p1=p->lchild;       //p指向*p的左子树根结点        if (p1->bf==1)      //新结点插入在*b的左孩子的左子树上,要作LL调整        {            p->lchild=p1->rchild;            p1->rchild=p;            p->bf=p1->bf=0;            p=p1;        }        else if (p1->bf==-1)    //新结点插入在*b的左孩子的右子树上,要作LR调整        {            p2=p1->rchild;            p1->rchild=p2->lchild;            p2->lchild=p1;            p->lchild=p2->rchild;            p2->rchild=p;            if (p2->bf==0)          //新结点插在*p2处作为叶子结点的情况                p->bf=p1->bf=0;            else if (p2->bf==1)     //新结点插在*p2的左子树上的情况            {                p1->bf=0;                p->bf=-1;            }            else                    //新结点插在*p2的右子树上的情况            {                p1->bf=1;                p->bf=0;            }            p=p2;            p->bf=0;            //仍将p指向新的根结点,并置其bf值为0        }        taller=0;    }}void RightProcess(BSTNode *&p,int &taller)//对以指针p所指结点为根的二叉树作右平衡旋转处理,本算法结束时,指针p指向新的根结点{    BSTNode *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;       //p指向*p的右子树根结点        if (p1->bf==-1)     //新结点插入在*b的右孩子的右子树上,要作RR调整        {            p->rchild=p1->lchild;            p1->lchild=p;            p->bf=p1->bf=0;            p=p1;        }        else if (p1->bf==1) //新结点插入在*p的右孩子的左子树上,要作RL调整        {            p2=p1->lchild;            p1->lchild=p2->rchild;            p2->rchild=p1;            p->rchild=p2->lchild;            p2->lchild=p;            if (p2->bf==0)          //新结点插在*p2处作为叶子结点的情况                p->bf=p1->bf=0;            else if (p2->bf==-1)    //新结点插在*p2的右子树上的情况            {                p1->bf=0;                p->bf=1;            }            else                    //新结点插在*p2的左子树上的情况            {                p1->bf=-1;                p->bf=0;            }            p=p2;            p->bf=0;            //仍将p指向新的根结点,并置其bf值为0        }        taller=0;    }}int InsertAVL(BSTNode *&b,KeyType e,int &taller)/*若在平衡的二叉排序树b中不存在和e有相同关键字的结点,则插入一个  数据元素为e的新结点,并返回1,否则返回0。若因插入而使二叉排序树  失去平衡,则作平衡旋转处理,布尔变量taller反映b长高与否*/{    if(b==NULL)         //原为空树,插入新结点,树“长高”,置taller为1    {        b=(BSTNode *)malloc(sizeof(BSTNode));        b->key=e;        b->lchild=b->rchild=NULL;        b->bf=0;        taller=1;    }    else    {        if (e==b->key)              //树中已存在和e有相同关键字的结点则不再插入        {            taller=0;            return 0;        }        if (e<b->key)               //应继续在*b的左子树中进行搜索        {            if ((InsertAVL(b->lchild,e,taller))==0) //未插入                return 0;            if (taller==1)          //已插入到*b的左子树中且左子树“长高”                LeftProcess(b,taller);        }        else                        //应继续在*b的右子树中进行搜索        {            if ((InsertAVL(b->rchild,e,taller))==0) //未插入                return 0;            if (taller==1)          //已插入到b的右子树且右子树“长高”                RightProcess(b,taller);        }    }    return 1;}void DispBSTree(BSTNode *b) //以括号表示法输出AVL{    if (b!=NULL)    {        printf("%d",b->key);        if (b->lchild!=NULL || b->rchild!=NULL)        {            printf("(");            DispBSTree(b->lchild);            if (b->rchild!=NULL) printf(",");            DispBSTree(b->rchild);            printf(")");        }    }}void LeftProcess1(BSTNode *&p,int &taller)  //在删除结点时进行左处理{    BSTNode *p1,*p2;    if (p->bf==1)    {        p->bf=0;        taller=1;    }    else if (p->bf==0)    {        p->bf=-1;        taller=0;    }    else        //p->bf=-1    {        p1=p->rchild;        if (p1->bf==0)          //需作RR调整        {            p->rchild=p1->lchild;            p1->lchild=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;            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;            taller=1;        }    }}void RightProcess1(BSTNode *&p,int &taller) //在删除结点时进行右处理{    BSTNode *p1,*p2;    if (p->bf==-1)    {        p->bf=0;        taller=-1;    }    else if (p->bf==0)    {        p->bf=1;        taller=0;    }    else        //p->bf=1    {        p1=p->lchild;        if (p1->bf==0)          //需作LL调整        {            p->lchild=p1->rchild;            p1->rchild=p;            p1->bf=-1;            p->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;            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;            taller=1;        }    }}void Delete2(BSTNode *q,BSTNode *&r,int &taller)//由DeleteAVL()调用,用于处理被删结点左右子树均不空的情况{    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)            RightProcess1(r,taller);    }}int DeleteAVL(BSTNode *&p,KeyType x,int &taller) //在AVL树p中删除关键字为x的结点{    int k;    BSTNode *q;    if (p==NULL)        return 0;    else if (x<p->key)    {        k=DeleteAVL(p->lchild,x,taller);        if (taller==1)            LeftProcess1(p,taller);        return k;    }    else if (x>p->key)    {        k=DeleteAVL(p->rchild,x,taller);        if (taller==1)            RightProcess1(p,taller);        return k;    }    else            //找到了关键字为x的结点,由p指向它    {        q=p;        if (p->rchild==NULL)        //被删结点右子树为空        {            p=p->lchild;            free(q);            taller=1;        }        else if (p->lchild==NULL)   //被删结点左子树为空        {            p=p->rchild;            free(q);            taller=1;        }        else                        //被删结点左右子树均不空        {            Delete2(q,q->lchild,taller);            if (taller==1)                LeftProcess1(q,taller);            p=q;        }        return 1;    }}int main(){    BSTNode *b=NULL;    int i,j,k;    KeyType a[]= {16,3,7,11,9,26,18,14,15},n=9; //例10.5    printf(" 创建一棵AVL树:\n");    for(i=0; i<n; i++)    {        printf("   第%d步,插入%d元素:",i+1,a[i]);        InsertAVL(b,a[i],j);        DispBSTree(b);        printf("\n");    }    printf("   AVL:");    DispBSTree(b);    printf("\n");    printf(" 删除结点:\n");                     //例10.6    k=11;    printf("   删除结点%d:",k);    DeleteAVL(b,k,j);    printf("   AVL:");    DispBSTree(b);    printf("\n");    k=9;    printf("   删除结点%d:",k);    DeleteAVL(b,k,j);    printf("   AVL:");    DispBSTree(b);    printf("\n");    k=15;    printf("   删除结点%d:",k);    DeleteAVL(b,k,j);    printf("   AVL:");    DispBSTree(b);    printf("\n\n");    return 0;}

运行结果:



知识点:




0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小孩心烦气燥怎么办 情绪总是很烦躁怎么办 情绪不好爱生气怎么办 心里每天烦躁该怎么办 心情低落想哭怎么办 心老是烦躁急怎么办 易烦躁睡眠不好怎么办 天气热心情烦躁怎么办 嘴巴里有溃疡怎么办 嘴巴里面反复烂怎么办 多处口腔溃烂怎么办 口腔黏膜破了怎么办 有鼻炎鼻子痒怎么办 感冒就清鼻涕怎么办 怀孕感冒流鼻涕打喷嚏怎么办 过敏性鼻炎打喷嚏流鼻涕怎么办 宝宝黄鼻涕鼻塞怎么办 鼻炎总是打喷嚏流鼻涕怎么办 新生儿流黄鼻涕怎么办 感冒鼻塞流鼻涕喷嚏怎么办 宝宝总是打喷嚏流鼻涕怎么办 不停的打喷嚏流鼻涕怎么办 宝宝不停打喷嚏流鼻涕怎么办 孕妇感冒流鼻涕打喷嚏怎么办 孕妇感冒咳嗽流鼻涕怎么办 鼻子痒流鼻涕流眼泪怎么办 天冷鼻子流鼻涕怎么办 感冒流水样鼻涕怎么办 一直有清水鼻涕怎么办 孩子总打喷嚏鼻塞怎么办 4岁儿童流鼻涕怎么办 孕妇清鼻涕不停怎么办 感冒流鼻水怎么办速效办法 一岁宝宝流清涕怎么办 咳嗽喉咙痛有痰怎么办 冻感冒了流鼻涕怎么办 吸烟经常嗓子疼怎么办 擦鼻涕擦破了怎么办 感冒鼻水流不停怎么办 流鼻涕鼻子都擦红了怎么办 鼻子不停的流水怎么办