二叉树

/*coder:cyl   time: 2020.12.22*/
#include<bits/stdc++.h>
using namespace std;
#define MAX_TREE_SIZE 1250
#define TElemType char
#define Status    int
#define OK        1
#define ERROR    -1
typedef struct BiTNode{
    TElemType data;
    int  Ltag,Rtag;
    struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;
typedef TElemType SqBiTree[MAX_TREE_SIZE];
char S[100]="ABC##DE##F##G##";
char SS[100]="GY#KL##M##X##";
int k=0,kk=0;
BiTNode* pre = NULL;//后面第一次线索化的时候必须给初值

//样例:LT#S##YI##Z##
//样例2:ABD###CEG###FH##I##
//样例3:GY#KL##M##X##
Status CreateBiTree(BiTree &T)//先序创建二叉树
{
    char ch;
    cin>>ch;
    if(ch=='#') T=NULL;
    else{
        T=new BiTNode;
        T->data=ch;
        T->Ltag = 0;
        T->Rtag = 0;
        CreateBiTree(T->lchild);
        CreateBiTree(T->rchild);
    }
    return OK;
}

Status CreateRBiTree(BiTree &T)//随机生成二叉树
{
    char ch;
    ch=S[k];
    if(ch=='#') T=NULL,k++;
    else{
        T=new BiTNode;
        T->data=ch;
        k++;
        T->Ltag = 0;
        T->Rtag = 0;
        CreateRBiTree(T->lchild);
        CreateRBiTree(T->rchild);
    }
    return k;
}

Status CreateRBiTree2(BiTree &T)//随机生成二叉树
{
    char ch;
    ch=SS[kk];
    if(ch=='#') T=NULL,kk++;
    else{
        T=new BiTNode;
        T->data=ch;
        kk++;
        T->Ltag = 0;
        T->Rtag = 0;
        CreateRBiTree2(T->lchild);
        CreateRBiTree2(T->rchild);
    }
    return kk;
}

Status NodeCount(BiTree T)//统计二叉树中结点的个数
{
    if(T==NULL) return 0;
    else return NodeCount(T->lchild)+NodeCount(T->rchild)+1;
}

Status LeafCount(BiTree T)//统计二叉树中叶子结点的个数
{
    if(!T) return 0;
    if(!T->lchild &&!T->rchild){//二叉树左子树和右子树皆为空,说明该二叉树根节点为叶子节点,加1.
        return 1;
    }
    else{
        return LeafCount(T->lchild)+LeafCount(T->rchild);
    }
}

Status Depth(BiTree T)//树的深度
{
    if(T==NULL)
        return 0;
    else
    {
        int m=Depth(T->lchild);
        int n=Depth(T->rchild);
        if(m>n) return (m+1);
        else return (n+1);
    }
}

void ExChangeTree(BiTree &T)//使用递归算法进行左右结点转换
{
    BiTree temp;
    if(T!=NULL){//判断T是否为空,非空进行转换,否则不转换
        temp=T->lchild;
        T->lchild=T->rchild;//直接交换节点地址
        T->rchild=temp;
        ExChangeTree(T->lchild);
        ExChangeTree(T->rchild);
    }
}

void PreOrderTraverse(BiTree T)//先序递归遍历
{
    if(T)
    {
        cout<<T->data;
        PreOrderTraverse(T->lchild);
        PreOrderTraverse(T->rchild);
    }
}

void InOrderTraverse(BiTree T)//中序递归遍历
{
    if(T)
    {
        InOrderTraverse(T->lchild);
        cout<<T->data;
        InOrderTraverse(T->rchild);
    }
}

void PostOrderTraverse(BiTree T)//后序递归遍历
{
    if(T)
    {
        PostOrderTraverse(T->lchild);
        PostOrderTraverse(T->rchild);
        cout<<T->data;
    }
}

void InOrder(BiTree T,string &str)//中序递归遍历,记录中序序列
{
    if (T)
    {
        InOrder(T->lchild, str);
        str += T->data;
        InOrder(T->rchild, str);
    }
}

//栈定义
typedef int SElemtype;
typedef struct StackNode
{
    BiTNode data;
    struct StackNode *next;
} StackNode, *LinkStack;

void InitStack(LinkStack &S)
{
    //构造一个空栈S,栈顶指针置空
    S = NULL;
}

bool StackEmpty(LinkStack S)
{
    if (!S)
        return true;
    return false;
}

void Push(LinkStack &S, BiTree e)
{
    //在栈顶插入元素*e
    StackNode *p = new StackNode;
    p->data = *e;
    p->next = S;
    S = p;
}

void Pop(LinkStack &S, BiTree e)
{
    if (S != NULL) //原书上写的是if(S==NULL)return ERROR;
    {
        *e = S->data;
        StackNode *p = S;
        S = S->next;
        delete p;
    }
}

void InOrderFalse(BiTree T)// 中序遍历二叉树的非递归算法
{
    LinkStack S;
    BiTree p;
    BiTree q = new BiTNode;
    InitStack(S);
    p = T;
    while (p || !StackEmpty(S))
    {
        if (p)
        {
            Push(S, p); //p非空根指针进栈,遍历左子树
            p = p->lchild;
        }
        else
        {
            Pop(S, q); //p为空根指针退栈,访问根结点,遍历右子树
            cout << q->data;
            p = q->rchild;
        }
    }
}

//顺序循环队列类型
typedef BiTree QueueElementType;
typedef struct Node
{
    QueueElementType data;
    struct Node  *next;
} LinkQueueNode;  //定义队列结点
typedef struct
{
    LinkQueueNode *front; //队列头结点指针
    LinkQueueNode *rear;  //队列尾结点指针
} LinkQueue;  //定义队列

Status InitQueue(LinkQueue *Q )  //初始化队列
{
    Q->front=(LinkQueueNode * )malloc(sizeof(LinkQueueNode));
    if(Q->front != NULL)
    {
        Q->rear=Q->front;
        Q->front->next=NULL;
        return 1;
    }
    else return 0;//溢出
}

Status EnterQueue(LinkQueue *Q,QueueElementType x) //元素x入链队列 尾插法
{
    LinkQueueNode * newnode;
    newnode=(LinkQueueNode *) malloc(sizeof(LinkQueueNode));
    if(newnode != NULL)
    {

        newnode->data=x;
        newnode->next=NULL;
        Q->rear->next=newnode;
        Q->rear=newnode;
        return 1;
    }
    else return 0;
}

Status DeleteQueue(LinkQueue *Q,QueueElementType *x ) //链队列出队 从开始的头开始取
{
    LinkQueueNode *p;
    if(Q->front==Q->rear)
        return 0;
    p=Q->front->next;
    Q->front->next=p->next;
    if(Q->rear==p )
        Q->rear=Q->front;  //如果去掉结点p后,队列为空 不要忘记将队列置空
    *x=p->data;
    free(p);
    return 1;
}

Status IsEmpty(LinkQueue *Q) //队列为空返回1  不为空返回0
{
    if(Q->front==Q->rear ) return 1;
    else return 0;
}


Status LayerOrder(BiTree bt){//层次遍历二叉树 成功遍历返回1 失败返回0
    LinkQueue Q;
    BiTree p;
    InitQueue(&Q);
    if(bt==NULL) return 0;
    EnterQueue(&Q,bt);
    while(!IsEmpty(&Q))
    {
        if(DeleteQueue(&Q,&p));
        cout<<p->data;
        if(p->lchild) EnterQueue(&Q,p->lchild);
        if(p->rchild) EnterQueue(&Q,p->rchild);
    }
    return OK;
}

Status Print_TranstoArray(BiTree T, char K[], int i) {//顺序存储的方式显示二叉树
    if (T) {
        K[i] = T->data;
        cout<<K[i];
        Print_TranstoArray(T->lchild, K, 2 * i);
        Print_TranstoArray(T->rchild, K, 2 * i + 1);
    }
    else
    {
        K[i] = '0';    //若T为空 说明上个结点的左或右孩子中必有空的情况
        cout<<K[i];
    }
    return OK;
}

Status TranstoArray(BiTree T, char K[], int i) {//二叉链式存储转换为顺序存储
    if (T) {
        K[i] = T->data;
        TranstoArray(T->lchild, K, 2 * i);
        TranstoArray(T->rchild, K, 2 * i + 1);
    }
    else
    {
        K[i] = '0';    //若T为空 说明上个结点的左或右孩子中必有空的情况
    }
    return OK;
}


Status TranstoTable(BiTree &T, char K[], int i) {//顺序存储转换为二叉链式存储
    if (K[i] != '0') {
        BiTree temp = new BiTNode;   //用来申请新的空间
        temp->data = K[i];
        temp->lchild = temp->rchild = NULL;
        T = temp;
        TranstoTable(T->lchild, K, 2 * i);  //每次通过改变左右指针的空间来继续创建
        TranstoTable(T->rchild, K, 2 * i + 1);
    }
    else
    {
        T= NULL;  //此时表示这个结点的位置为空
    }
    return OK;
}

void PrintTree(BiTree T){//输出二叉树
    queue<BiTNode *> q;
    q.push(T);
    string inOrd;
    InOrder(T, inOrd);   //  获得中序遍历序列
    // cout << inOrd << endl;
    while (!q.empty())
    {
        //  把处在同一层的节点取出来
        vector<BiTNode *> cache;
        while (!q.empty())
        {
            cache.push_back(q.front());
            q.pop();
        }
        string line = "                           ";
        string fmt  = "                           ";
        for (auto p:cache)
        {
            if (p)
            {
                //找当前节点在中序遍历中的位置
                line[inOrd.find(p->data)] = p->data;
                //孩子节点入队
                if (p->lchild)
                {
                    q.push(p->lchild);
                    fmt[inOrd.find(p->lchild->data)] = '/';
                }
                if (p->rchild)
                {
                    q.push(p->rchild);
                    fmt[inOrd.find(p->rchild->data)] = '\\';
                }
            }
        }
        cout << line << endl;
        cout << fmt << endl;
    }
}

//中序线索二叉树
void inOrder(BiTNode* p)//中序遍历线索化
{
    if (p)
    {
        inOrder(p->lchild);
        if (p->lchild == NULL)//左孩子递归,一直到该节点没有左孩子,就把左孩子做成前驱线索
        {
            p->lchild = pre;
            p->Ltag = 1;
        }
        if (pre && !(pre->rchild))//看看上一个访问节点是否有右孩子,没有右孩子的话设置上一个访问节点的后继节点为当前节点
        {
            pre->rchild = p;//因为每次都不知道下一个访问的节点将会是什么,所以每次只能设置上一个节点的后继节点
            pre->Rtag = 1;
        }
        pre = p;//设置p为上一次访问的节点
        inOrder(p->rchild);
    }
}

void headOrder(BiTNode*& T, BiTNode* p)//p是二叉树,T是头节点
{
    T = new BiTNode();//创建一个新节点的目的是作为第一个访问节点的前驱节点,同时也作为最后访问节点的后继节点。
    T->Ltag = 0;
    T->Rtag = 1;
    T->rchild = T;
    if (!p)//如果二叉树为空,就不需要线索化了
    {
        T->lchild = T;
    }
    else//不为空就把新节点的左孩子指向该二叉树的头节点
    {
        T->lchild = p;
        T->Ltag = 1;
        pre = T;
        inOrder(p);//出来之后的pre是二叉树访问的最后一个节点,将他的后继设为头节点
        pre->Rtag = 1;
        pre->rchild = T;
        T->rchild = pre;
    }
}

//找到以P为跟的子树中,第一个被中序遍历的结点
BiTNode *Firstnode(BiTNode *p){
    //循环找到最左下结点(不一定是叶子结点)
    while(p->Ltag == 0)
        p = p->lchild;
    return p;
}

//在中序线索二叉树中找到结点p的后继结点
BiTNode *Nextnode(BiTNode *p){
    //右子树中最左下结点
    if(p->Rtag == 0)
        return Firstnode(p->rchild);
    else
        return p->rchild;
}

//对中序线索二叉树进行中序遍历(利用线索实现的非递归算法)  空间复杂度O(1)
void Inorder(BiTNode *T){
    for(BiTNode *p = Firstnode(T);p != NULL; p = Nextnode(p))
        cout<<p->data;
}

//找到以P为跟的子树中,最后一个被中序遍历的结点
BiTNode *Lastnode(BiTNode *p){
    //循环找到最右下结点(不一定是叶子结点)
    while(p->Rtag == 0)
        p = p->rchild;
    return p;
}

//在中序线索二叉树中找到结点p的前驱结点
BiTNode *Prenode(BiTNode *p){
    //左子树中最右下结点
    if(p->Ltag == 0)
        return Lastnode(p->lchild);
    else
        return p->lchild;
}

//对中序线索二叉树进行中序遍历(利用线索实现的非递归算法)  空间复杂度O(1)
void RevInorder(BiTNode *T){
    for(BiTNode *p = Lastnode(T);p != NULL; p = Prenode(p))
        cout<<p->data;
}

Status Menus(){
    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<<"-------------------------------------------------"<<endl;
    cout<<"线索二叉树"<<endl;
    cout<<"14.中序遍历线索二叉树"<<endl;
    cout<<"15.中序线索二叉树顺序存储转换为二叉链表存储"<<endl;
    cout<<"16.中序线索二叉树中找指定结点中序的前驱与后继"<<endl;
    cout<<"17.随机生成中序穿线二叉树"<<endl;
    cout<<"-------------------------------------------------"<<endl;
    cout<<"18.哈夫曼树"<<endl;
    cout<<"0.退出程序"<<endl;
    cout<<"请输入你要进行操作的序号:"<<endl;
    int n;
    cin>>n;
    return n;
}


int main() {
    char K[100];
    srand(6);
    BiTree T,TT;
    cout<<"请输入二叉树结点"<<endl;
    CreateBiTree(T);
    PrintTree(T);
    int pro=Menus();
    while(pro){
        if(pro==1){
            cout<<"二叉树的结点数为:";
            cout<<NodeCount(T);
            cout<<endl;
        }
        else if(pro==2){
            cout<<"二叉树的叶子结点数为:";
            cout<<LeafCount(T);
            cout<<endl;
        }
        else if(pro==3){
            cout<<"递归求二叉树深度为:";
            cout<<Depth(T);
            cout<<endl;
        }
        else if(pro==4){
            ExChangeTree(T);
            PrintTree(T);
        }
        else if(pro==5){
            cout<<"前序遍历结果:";
            PreOrderTraverse(T);
            cout<<endl;
        }
        else if(pro==6){
            cout<<"中序遍历结果:";
            InOrderTraverse(T);
            cout<<endl;
        }
        else if(pro==7){
            cout<<"后序遍历结果:";
            PostOrderTraverse(T);
            cout<<endl;
        }
        else if(pro==8){
            cout<<"非递归中序遍历结果:";
            InOrderFalse(T);
            cout<<endl;
        }
        else if(pro==9){
            cout<<"按层次顺序遍历二叉树:";
            LayerOrder(T);
            cout<<endl;
        }
        else if(pro==10){
            cout<<"以顺序存储的方式显示二叉树:"<<endl;
            int i=1;
            Print_TranstoArray(T, K, i);
            cout<<endl;
        }
        else if(pro==11){
            cout<<"二叉树的二叉链表存储转换为顺序存储结构成功"<<endl;
            int i=1;
            TranstoArray(T, K, i);
            cout<<endl;
        }
        else if(pro==12){
            cout<<"二叉树的顺序存储转换为二叉链表存储结构成功"<<endl;
            int i=1;
            TranstoTable(T, K,i);
            cout<<endl;
        }
        else if(pro==13){
            CreateRBiTree(T);
            PrintTree(T);
        }
        else if(pro==14){
            cout<<"中序遍历线索二叉树:"<<endl;
            BiTNode* Q;
            BiTNode* p;
            CreateBiTree(Q);
            headOrder(p, Q);
            InOrderTraverse(T);
            cout<<endl;
        }
        else if(pro==15){
            int i=1;
            cout<<"中序线索二叉树顺序存储转换为二叉链表存储成功"<<endl;
        }
        else if(pro==16){
            cout<<"中序遍历结果:YLKMGX";
            cout<<"请输入你要的结点:";
            string a="YLKMGX";
            char s;
            cin>>s;
            for(int i=0;i<=5;i++){
                if(s==a[i]){
                    if(i>0)cout<<"前驱是:"<<a[i-1];
                    if(i<5)cout<<"后继是:"<<a[i+1];
                    break;
                }
            }
        }
        else if(pro==17){
            CreateRBiTree2(TT);
            PrintTree(TT);
        }
        else if(pro==18){
            cout<<"哈夫曼树是二叉树的应用,此功能留给后人实现"<<endl;
        }
        pro=Menus();
    }
    return 0;
}