zl程序教程

您现在的位置是:首页 >  后端

当前栏目

二叉树的基本操作(顺序二叉树)

二叉树 顺序 基本操作
2023-09-14 08:56:53 时间

该代码的二叉树结点是数字,采用的是用数组存储,一般使用在空结点较少的情况,使用的时候,一定要清楚二叉树元素在数组中的存储顺序特点,比如左右子树序号有什么特点,怎么由孩子结点的找到双亲节点……

如果想了解链式存储二叉树,可以参考http://www.cnblogs.com/-beyond/p/6200478.html

#include<iostream>
#include<cmath>
#include<cstdlib>
using namespace std;

const int MAX_TREE_SIZE=100;
const int Nil=0;
typedef int TElemType;
typedef int SqBiTree[MAX_TREE_SIZE];

struct position{
    //按满二叉树计算
    int level,order;
};

//函数声明
void show();
void InitBiTree(SqBiTree T);
void DestroyBiTree(SqBiTree T);
void CreateBiTree(SqBiTree T);
int ClearBiTree(SqBiTree T);
bool EmptyBiTree(SqBiTree T);
int BiTreeDepth(SqBiTree T);
TElemType BiTreeRoot(SqBiTree T);
TElemType GetValue(SqBiTree T,position e);
bool Assign(SqBiTree T,position e,TElemType value);
TElemType Parent(SqBiTree T,TElemType e);
TElemType LeftChild(SqBiTree T,TElemType e);
TElemType RightChild(SqBiTree T,TElemType e);
TElemType LeftSibling(SqBiTree T,TElemType e);
TElemType RightSibling(SqBiTree T,TElemType e);
void InsertChild(SqBiTree T,TElemType p,int LR,SqBiTree c);
void Move(SqBiTree q,int j,SqBiTree T,int i);
void PreOrderTraverse(SqBiTree T,int i);
void InOrderTraverse(SqBiTree T,int i);
void PostOrderTraverse(SqBiTree T,int i);
void LevelOrderTraverse(SqBiTree T);
void Print(SqBiTree T);

int main(){
    int x,LR,action;
    position p;
    TElemType e;
    SqBiTree T,s;
    show();
    while(cin>>action){
        switch(action){
        case 1:
            system("cls");
            InitBiTree(T);
            cout<<"初始化二叉树成功"<<endl<<endl;
            break;
        case 2:
            system("cls");
            CreateBiTree(T);
            cout<<"二叉树创建成功"<<endl<<endl;
            break;
        case 3:
            system("cls");
            cout<<"先序遍历二叉树,结果为:"<<endl;
            PreOrderTraverse(T,0);
            cout<<endl<<endl;
            break;
        case 4:
            system("cls");
            cout<<"中序遍历二叉树,结果为:"<<endl;
            InOrderTraverse(T,0);
            cout<<endl<<endl;
            break;
        case 5:
            system("cls");
            cout<<"后序遍历二叉树,结果为:"<<endl;
            PostOrderTraverse(T,0);
            cout<<endl<<endl;
            break;
        case 6:
            system("cls");
            cout<<"层序遍历二叉树,结果为:"<<endl;
            LevelOrderTraverse(T);
            cout<<endl<<endl;
            break;
        case 7:
            system("cls");
            cout<<"请输入层数和序号:"<<endl;
            cin>>p.level>>p.order;
            cout<<"第"<<p.level<<"层"<<" 第"<<p.order<<"个结点的值为: "<<GetValue(T,p);
            cout<<endl<<endl;
            break;
        case 8:
            system("cls");
            ClearBiTree(T);
            cout<<"已清空二叉树"<<endl<<endl;
            break;
        case 9:
            InitBiTree(s);
            cout<<"请输入右子树为空的二叉树s:"<<endl;
            CreateBiTree(s);
            cout<<"待插入的二叉树已经建立,请输入将要插入的结点的值:"<<endl;
            cin>>e;
            cout<<"待插入的二叉树成为左孩子(0),右孩子(1):"<<endl;
            cin>>LR;
            InsertChild(T,e,LR,s);
            cout<<"操作成功"<<endl<<endl;
            break;
        case 10:
            system("cls");
            cout<<"二叉树的各结点为:"<<endl;
            Print(T);
            cout<<endl;
            break;
        case 11:
            system("cls");
            cout<<"请输入双亲结点"<<endl;
            cin>>e;
            cout<<"左孩子结点的值为: "<<LeftChild(T,e)<<endl;
            break;
        case 12:
            system("cls");
            cout<<"请输入双亲结点"<<endl;
            cin>>e;
            cout<<"右孩子结点的值为: "<<RightChild(T,e)<<endl;
            break;
        case 13:
            system("cls");
            cout<<"请输入右兄弟结点"<<endl;
            cin>>e;
            cout<<"左兄弟结点的值为: "<<LeftSibling(T,e)<<endl;
            break;
        case 14:
            system("cls");
            cout<<"请输入左兄弟结点"<<endl;
            cin>>e;
            cout<<"右兄弟结点的值为: "<<RightSibling(T,e)<<endl;
            break;
        case 15:
            system("cls");
            cout<<"请输入孩子结点"<<endl;
            cin>>e;
            cout<<"双亲结点的值为: "<<Parent(T,e)<<endl;
            break;
        case 16:
            system("cls");
            cout<<"二叉树的深度为: "<<BiTreeDepth(T)<<endl;
            break;
        case 17:
            system("cls");
            cout<<"根结点的值为: "<<BiTreeRoot(T)<<endl;
            break;
        case 18:
            system("cls");
            cout<<"请输入结点的层数和在该层的序号: "<<endl;
            cin>>p.level>>p.order;
            cout<<"请输入将赋给该结点的值:"<<endl;
            cin>>e;
            Assign(T,p,e);
            cout<<"赋值成功!"<<endl;
            break;
        }
        system("pause");
        system("cls");
        show();
    }


}
void show(){
    cout<<"+-----------------------------------------------+"<<endl;
    cout<<"|                                               |"<<endl;
    cout<<"|         1->初始化二叉树                       |"<<endl;
    cout<<"|         2->创建二叉树                         |"<<endl;
    cout<<"|         3->先序遍历二叉树                     |"<<endl;
    cout<<"|         4->中序遍历二叉树                     |"<<endl;
    cout<<"|         5->后序遍历二叉树                     |"<<endl;
    cout<<"|         6->层序遍历二叉树                     |"<<endl;
    cout<<"|         7->获取树结点的值                     |"<<endl;
    cout<<"|         8->清空二叉树                         |"<<endl;
    cout<<"|         9->插入二叉树                         |"<<endl;
    cout<<"|        10->打印二叉树                         |"<<endl;
    cout<<"|        11->获取左孩子                         |"<<endl;
    cout<<"|        12->获取右孩子                         |"<<endl;
    cout<<"|        13->获取左兄弟                         |"<<endl;
    cout<<"|        14->获取右兄弟                         |"<<endl;
    cout<<"|        15->获取结点双亲                       |"<<endl;
    cout<<"|        16->获取二叉树深度                     |"<<endl;
    cout<<"|        17->获取根节点                         |"<<endl;
    cout<<"|        18->给结点赋值                         |"<<endl;
    cout<<"+-----------------------------------------------+"<<endl;

}

void InitBiTree(SqBiTree T){
    int i;
    for(i=0;i<MAX_TREE_SIZE;i++){
        T[i]=Nil;//初始值为Nil
    }
}

void DestroyBiTree(SqBiTree T){
    int i;
    for(i=0;i<MAX_TREE_SIZE;i++){
        T[i]=Nil;//初始值为Nil
    }
}

void CreateBiTree(SqBiTree T){
    int i=0;
    cout<<"请按层需输入结点的值(数字),0表示空结点,以999结束,结点数<"<<MAX_TREE_SIZE<<":"<<endl;
    while(1){
        cin>>T[i];
        if(T[i]==999){
            T[i]=Nil;
            break;
        }
        i++;
    }
    for(i=1;i<MAX_TREE_SIZE;i++){
        if(i!=0 && T[(i+1)/2-1]==Nil && T[i]!=Nil){
            cout<<"出现无双亲的非根节点!"<<endl;
            break;
        }
    }
}

int ClearBiTree(SqBiTree T){
    int i;
    for(i=0;i<MAX_TREE_SIZE;i++){
        T[i]=Nil;//初始值为Nil
    }
}

//判断二叉树是否为空
bool EmptyBiTree(SqBiTree T){
    if(T[0]==Nil){
        return true;
    } else {
        return false;
    }
}

//获取二叉树的深度
int BiTreeDepth(SqBiTree T){
    int i=MAX_TREE_SIZE-1,j=0;
    while(i>=0){
        //从后往前寻找到第一个结点不是默认值的下标
        if(T[i]!=Nil){
            break;
        }
        i--;
    }
    while(i>=pow(2,j)){
        j++;
    }
    return j;
}

//获取根结点的值
TElemType BiTreeRoot(SqBiTree T){
    if(EmptyBiTree(T)){
        return Nil;
    } else {
        return T[0];
    }
}

//获取给定结点e的值
TElemType GetValue(SqBiTree T,position e){
    return T[int(pow(2,e.level-1)+e.order-2)];
}

//给结点赋值
bool Assign(SqBiTree T,position e,TElemType value){
    int i=pow(2,e.level-1)+e.order-2;
    if(value!=Nil && T[(i+1)/2-1]==Nil){
        cout<<"非法操作,禁止给不含双亲的孩子赋非空值"<<endl;
        return false;
    }
    else if(value==Nil && (T[i*2+1]!=Nil || T[i*2+2]!=Nil)){
        cout<<"非法操作,禁止给含有孩子的双亲赋空值"<<endl;
        return false;
    }
    T[i]=value;
    return true;
}

//获取双亲结点的值
TElemType Parent(SqBiTree T,TElemType e){
    if(!EmptyBiTree(T)){
        for(int i=0;i<=MAX_TREE_SIZE;i++){
            if(T[i]==e){//判断结点e是否存在与二叉树中
                return T[(i+1)/2-1];
            }
        }
    } else {
        return Nil;//二叉树为空或者没有结点e
    }
}

//获取左孩子的值
TElemType LeftChild(SqBiTree T,TElemType e){
    if(!EmptyBiTree(T)){
        for(int i=0;i<MAX_TREE_SIZE;i++){
            if(T[i]==e){//判断结点e是否存在与二叉树中
                return T[i*2+1];//返回其左孩子的值
            }
        }
    } else {
        return Nil;//二叉树为空或者没有结点e
    }
}

//获取右孩子的值
TElemType RightChild(SqBiTree T,TElemType e){
    if(!EmptyBiTree(T)){
        for(int i=0;i<MAX_TREE_SIZE;i++){
            if(T[i]==e){//判断结点e是否存在与二叉树中
                return T[i*2+2];//返回其左孩子的值
            }
        }
    } else {
        return Nil;//二叉树为空或者没有结点e
    }
}

//获取左兄弟的值
TElemType LeftSibling(SqBiTree T,TElemType e){
     if(!EmptyBiTree(T)){
        for(int i=0;i<MAX_TREE_SIZE;i++){
            if(T[i]==e && i%2==0){//判断结点e是否存在与二叉树中
                //并且存在有兄弟,i%2=0为右孩子
                return T[i-1];//返回其左兄弟的值
            }
        }
    } else {
        return Nil;//二叉树为空或者没有结点e
    }
}

//获取右兄弟的值
TElemType RightSibling(SqBiTree T,TElemType e){
     if(!EmptyBiTree(T)){
        for(int i=0;i<MAX_TREE_SIZE;i++){
            if(T[i]==e && i%2==1){//判断结点e是否存在与二叉树中
                //并且存在有兄弟,i%2==1为左孩子
                return T[i+1];//返回其右兄弟的值
            }
        }
    } else {
        return Nil;//二叉树为空或者没有右兄弟
    }
}
//仔细观察,寻找双亲、左右孩子和左右兄弟的方法都类似
//首先都得判断二叉树是否为空,然后再判断时候该结点是否存在
//最后根据判断返回结点值

//插入二叉树
void InsertChild(SqBiTree T,TElemType p,int LR,SqBiTree c){
    //非空二叉树c要插到T中的p结点下面,成为p结点的(左或右)子树
    //非空二叉树c与T无交集,且右子树为空,p结点原有的左或右子树成为s的右子树
    //LR=0 c成为左子树,LR=1 c成为右子树
    int i=0,j,k;
    //查找p结点的序号
    //int temp=int(pow(2,BiTreeDepth(T)));
    //for(j=0;j<temp-1;j++){
    //  if(T[j]==p){
    //      break;
    //  }
    //}
    //或者
    for(j=0;j<MAX_TREE_SIZE;j++){
        if(T[j]==p){
            break;
        }
    }
    k=2*j+1+LR;//k为c子树将要插入的序号
    if(T[k]!=Nil){
        Move(T,k,T,2*k+2);
    }
    Move(c,i,T,k);
}

//移动二叉树
void Move(SqBiTree q,int j,SqBiTree T,int i){
    //把从二叉树q的j结点开始的子树 移为 从二叉树T的i结点开始的子树
    if(q[2*j+1]!=Nil){//q的左子树不为空
        Move(q,(2*j+1),T,(2*i+1));
    }
    if(q[2*j+2]!=Nil){//q的右子树不为空
        Move(q,(2*j+2),T,(2*i+2));
    }
    T[i]=q[j];
    q[i]=Nil;
}

//先序遍历
void PreOrderTraverse(SqBiTree T,int i){
    cout<<T[i]<<' ';
    if(T[2*i+1]!=Nil){
        PreOrderTraverse(T,2*i+1);
    }
    if(T[2*i+2]!=Nil){
        PreOrderTraverse(T,2*i+2);
    }
}

//中序遍历
void InOrderTraverse(SqBiTree T,int i){
    if(T[2*i+1]!=Nil){
        InOrderTraverse(T,2*i+1);
    }
    cout<<T[i]<<' ';
    if(T[2*i+2]!=Nil){
        InOrderTraverse(T,2*i+2);
    }
}

//后序遍历
void PostOrderTraverse(SqBiTree T,int i){
    if(T[2*i+1]!=Nil){
        PostOrderTraverse(T,2*i+1);
    }
    if(T[2*i+2]!=Nil){
        PostOrderTraverse(T,2*i+2);
    }
    cout<<T[i]<<' ';
}

//层序遍历
void LevelOrderTraverse(SqBiTree T){
    int i=MAX_TREE_SIZE-1;
    while(T[i]==Nil){
        i--;
    }
    for(int j=0;j<=i;j++){
        if(T[j]!=Nil){
            cout<<T[j]<<' ';
        }
    }
    cout<<endl;
}

//逐层按本层序号输出二叉树
void Print(SqBiTree T){
    int j,k;
    position p;
    TElemType e;
    for(j=1;j<=BiTreeDepth(T);j++){
        cout<<"第"<<j<<"层: ";
        for(k=1;k<=pow(2,j-1);k++){
            p.level=j;
            p.order=k;
            e=GetValue(T,p);
            cout<<k<<":"<<e<<"     ";
        }
        cout<<endl;
    }
    cout<<endl;
}