【数据结构6】二叉树的基本操作

⭐️写在前面的话⭐️

📒博客主页: 程序员好冰
🎉欢迎 【点赞👍 关注🔎 收藏⭐️ 留言📝】
📌本文由 程序员好冰 原创,CSDN 首发!
📆入站时间: 🌴2022 年 07 月 13 日🌴
✉️ 是非不入松风耳,花落花开只读书。
💭推荐书籍:📚《Java编程思想》,📚《Java 核心技术卷》
💬参考在线编程网站:🌐牛客网🌐力扣
🍭 作者水平很有限,如果发现错误,一定要及时告知作者哦!感谢感谢!🍭


二叉树的一些基本操作

1、结构定义

#include <stdio.h>
#include <stdlib.h>

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW -1

#define Nil '#'

#define MAX_SIZE 1024

typedef int Status;
typedef char ElemType;

typedef struct BiTNode
{
    ElemType data;
    struct BiTNode *LChild,*RChild;
    /*
    左标志,0为指向左子节点,1为指向前驱(即线索)
    右标志,0为指向右子节点,1为指向后继(即线索)
    */
    int Ltag,Rtag;//供线索化二叉树使用
}BiTNode,*BiTree;

2、先序创建这棵树

void PreCreateBiTree(BiTree *T)
{
    ElemType ch;
    getchar();
    ch=getchar();
    if(ch==Nil){
        *T=NULL;//说明这棵子树为空
    }
    if(ch!=Nil){
        *T=(BiTree)malloc(sizeof(BiTNode));
        (*T)->data=ch;
        /*线索化线索化二叉树增加的*/(*T)->Ltag=(*T)->Rtag=0;
        PreCreateBiTree(&((*T)->LChild));
        PreCreateBiTree(&((*T)->RChild));
    }
}

3、按满二叉树方式创建

void FullCreateBiTree(BiTree *T)
{
    BiTNode *p;
    BiTNode *arr[MAX_SIZE];
    char ch;
    int i,j;
    while(1){
        scanf("%d",&i);
        getchar();
        if(i==0){
            break;
        }
        if(i!=0){
            ch=getchar();
            if(ch==Nil){
                continue;
            }
            p=(BiTNode*)malloc(sizeof(BiTNode));
            p->data=ch;
            p->Ltag=p->Rtag=0;
            p->LChild=NULL;
            p->RChild=NULL;
            arr[i]=p;
            if(i==1){
                *T=p;
            }
            if(i!=1){
                j=i/2;
                if(i%2==0){
                    arr[j]->LChild=p;
                }
                if(i%2!=0){
                    arr[j]->RChild=p;
                }
            }
        }
    }
}

4、三种递归遍历

//先序递归遍历
void PreOrderTraverse(BiTree T)
{
    if(T==NULL){
        return;
    }
    printf("%c ",T->data);
    PreOrderTraverse(T->LChild);
    PreOrderTraverse(T->RChild);
}


//中序递归遍历
void InOrderTraverse(BiTree T)
{
    if(T==NULL){
        return;
    }
    InOrderTraverse(T->LChild);
    printf("%c ",T->data);
    InOrderTraverse(T->RChild);
}

//后序递归遍历
void PostOrderTraverse(BiTree T)
{
    if(T==NULL){
        return;
    }
    PostOrderTraverse(T->LChild);
    PostOrderTraverse(T->RChild);
    printf("%c ",T->data);
}

5、层次遍历

/*构建队列*/
int front=0,rear=0;
void EnQueue(BiTree *t,BiTree node)
{//结点入队
    if(rear==MAX_SIZE){
        exit(0);
    }
    t[rear++]=node;
}
BiTNode* DeQueue(BiTree *t)
{//结点出队
    if(front==rear){
        exit(0);
    }
    return t[front++];
}
void LevelOrderTraverse(BiTree T)
{
    if(T){
        BiTree t[MAX_SIZE]={0};
        BiTNode *p=NULL;
        p=T;
        EnQueue(t,p);
        while(front<rear)
        {
            p=DeQueue(t);
            printf("%c ",p->data);
            if(p->LChild){
                EnQueue(t,p->LChild);
            }
            if(p->RChild){
                EnQueue(t,p->RChild);
            }
        }
    }
}

6、求二叉树的深度

int BiTreeDepth(BiTree T)
{
    int left=0,right=0;
    if(!T){
        return 0;
    }
    if(T->LChild){
        left=BiTreeDepth(T->LChild);
    }
    if(T->RChild){
        right=BiTreeDepth(T->RChild);
    }
    return left>right?left+1:right+1;
}

7、求叶子结点数

int Count_Leaves(BiTree T)
{
    if(!T){
        return 0;
    }
    if(!(T->LChild)&&!(T->RChild)){
        return 1;
    }
    return Count_Leaves(T->LChild)+Count_Leaves(T->RChild);
}

8、三种非递归遍历

//先序非递归遍历
void PreOrderTraverse2(BiTree T)
{
    if(!T)
    {
        return;
    }
    //创建一个数组来模拟栈
    BiTree stack[MAX_SIZE]={0};
    int top=-1;
    stack[++top]=T;
    while(top>-1){
       BiTree node=stack[top--];
        printf("%c ",node->data);
        if(node->RChild){stack[++top]=node->RChild;}
        if(node->LChild){stack[++top]=node->LChild;}
    }
}

//中序非递归遍历
void InOrderTraverse2(BiTree T)
{
    if(!T){
        return;
    }
    BiTree stack[MAX_SIZE]={0};
    int top=-1;
    BiTree node=T;
    while(top>-1||node!=NULL){
        while(node!=NULL){//一直深入左节点
            stack[++top]=node;
            node=node->LChild;
        }
        node=stack[top--];
        printf("%c ",node->data);
        node=node->RChild;
    }
}

//后序非递归遍历
void PostOrderTraverse2(BiTree T)
{
     if(!T){
        return;
     }
     BiTree stack1[MAX_SIZE]={0};
     BiTree stack2[MAX_SIZE]={0};
     int top1=-1;
     int top2=-1;
     BiTree node=T;
     stack1[++top1]=node;
     while(top1>-1){
        node=stack1[top1--];
        stack2[++top2]=node;
        if(node->LChild!=NULL){stack1[++top1]=node->LChild;}
        if(node->RChild!=NULL){stack1[++top1]=node->RChild;}
    }
    while(top2>-1){
        printf("%c ",stack2[top2--]->data);
    }
}

9、先序线索化二叉树

BiTree pre=NULL;// 全局变量,用于记录前驱节点
void PreOrder_Threading(BiTree T)
{
    if(T==NULL){return;}
    if(T->LChild ==NULL){
        T->Ltag=1;
        T->LChild=pre;//Ltag为1,指向前驱
    }
    if(pre!=NULL && pre->RChild==NULL){
        pre->Rtag=1;
        pre->RChild=T;//Rtag为1,指向后继
    }
    pre=T;
    if(T->Ltag==0){PreOrder_Threading(T->LChild);}
    if(T->Rtag==0){PreOrder_Threading(T->RChild);}
}

10、先序线索化后遍历

void PreOrder_Threading_Traverse(BiTree T)
{
    BiTree temp=T;
    while(temp!=NULL){
        printf("%c ",temp->data);
        if(temp->Ltag==0){
            temp=temp->LChild;
        }else
        {
            temp=temp->RChild;//寻找后继
        }
    }
}

11、中序线索化二叉树

BiTree pre2=NULL;// 全局变量,用于记录前驱节点
void InOrder_Threading(BiTree T)
{
    if(T==NULL){return;}

    if(T->Ltag==0){InOrder_Threading(T->LChild);}//深入到树的最左边的结点
    if(T->LChild ==NULL){
        T->Ltag=1;
        T->LChild=pre2;//Ltag为1,指向前驱
    }
    if(pre2!=NULL && pre2->RChild==NULL){
        pre2->Rtag=1;
        pre2->RChild=T;//Rtag为1,指向后继
    }
    pre2=T;
    if(T->Rtag==0){InOrder_Threading(T->RChild);}
}

12、中序线索化后遍历

void InOrder_Threading_Traverse(BiTree T)
{
    BiTree p=T;
    while(p){
        while(p->Ltag==0){
            p=p->LChild;
        }//深入到最左边的结点
        printf("%c ",p->data);
        while(p->Rtag==1&&p->RChild!=NULL){
            //p->RChild!=NULL说明不是最后一个结点,这个接地那没有后继,指向NULL
            p=p->RChild;//找到后继节点
            printf("%c ",p->data);
        }
        p=p->RChild;
    }
}

主函数

int main()
{
    BiTree T;
    int flag;
    printf("请输入需要的创建方式(1为先序,2为满二叉):");
    scanf("%d",&flag);
    switch(flag)
    {
    case 1://先序创建这棵树
        printf("按先序方式创建这棵树pre_T('#'表示空):\n");
        PreCreateBiTree(&T);
        printf("成功.\n");
        break;
    case 2://按满二叉树方式创建
        printf("按满二叉树方式创建这棵树full_T(以 1 A 为输入0结束例):\n");
        FullCreateBiTree(&T);
        printf("成功.\n");
        break;
    default:
        printf("你输入的序号有误.\n");
        break;
    }

    //递归遍历(三种:前中后)
    printf("先序递归的结果:");
    PreOrderTraverse(T);
    printf("\n");
    printf("成功.\n");
    printf("中序递归的结果:");
    InOrderTraverse(T);
    printf("\n");
    printf("成功.\n");
    printf("后序递归的结果:");
    PostOrderTraverse(T);
    printf("\n");
    printf("成功.\n");

    //非递归遍历(三种:前中后)
    printf("先序非递归的结果:");
    PreOrderTraverse2(T);
    printf("\n");
    printf("成功.\n");
    printf("中序非递归的结果:");
    InOrderTraverse2(T);
    printf("\n");
    printf("成功.\n");
    printf("后序非递归的结果:");
    PostOrderTraverse2(T);
    printf("\n");
    printf("成功.\n");


    //层次遍历
    printf("层序遍历的结果:");
    LevelOrderTraverse(T);
    printf("\n");
    printf("成功.\n");


    //求叶子结点数
    printf("这棵树的叶子结点数为:%d.\n",Count_Leaves(T));
    //求二叉树的深度
    printf("这棵树的深度为:%d.\n",BiTreeDepth(T));

    printf("================\n");
    printf("1、先序线索化.\n");
    printf("2、中序线索化.\n");
    printf("请输入需要线索化的形式:");
    int flag2;
    scanf("%d",&flag2);
    switch(flag2)
    {
        case 1:
            //先序线索化二叉树并遍历
            PreOrder_Threading(T);
            printf("先序线索化二叉树并遍历,结果为:");
            PreOrder_Threading_Traverse(T);
            break;
        case 2:
            //中序线索化二叉树并遍历
            InOrder_Threading(T);
            printf("中序线索化二叉树并遍历,结果为:");
            InOrder_Threading_Traverse(T);
            break;
        default:
            printf("你输入的序号有误.\n");
            break;
    }
    return 0;
}

程序源码

#include <stdio.h>
#include <stdlib.h>

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW -1

#define Nil '#'

#define MAX_SIZE 1024

typedef int Status;
typedef char ElemType;

typedef struct BiTNode
{
    ElemType data;
    struct BiTNode *LChild,*RChild;
    /*
    左标志,0为指向左子节点,1为指向前驱(即线索)
    右标志,0为指向右子节点,1为指向后继(即线索)
    */
    int Ltag,Rtag;//供线索化二叉树使用
}BiTNode,*BiTree;


//先序创建这棵树
void PreCreateBiTree(BiTree *T)
{
    ElemType ch;
    getchar();
    ch=getchar();
    if(ch==Nil){
        *T=NULL;//说明这棵子树为空
    }
    if(ch!=Nil){
        *T=(BiTree)malloc(sizeof(BiTNode));
        (*T)->data=ch;
        /*线索化线索化二叉树增加的*/(*T)->Ltag=(*T)->Rtag=0;
        PreCreateBiTree(&((*T)->LChild));
        PreCreateBiTree(&((*T)->RChild));
    }
}

//按满二叉树方式创建
void FullCreateBiTree(BiTree *T)
{
    BiTNode *p;
    BiTNode *arr[MAX_SIZE];
    char ch;
    int i,j;
    while(1){
        scanf("%d",&i);
        getchar();
        if(i==0){
            break;
        }
        if(i!=0){
            ch=getchar();
            if(ch==Nil){
                continue;
            }
            p=(BiTNode*)malloc(sizeof(BiTNode));
            p->data=ch;
            p->Ltag=p->Rtag=0;
            p->LChild=NULL;
            p->RChild=NULL;
            arr[i]=p;
            if(i==1){
                *T=p;
            }
            if(i!=1){
                j=i/2;
                if(i%2==0){
                    arr[j]->LChild=p;
                }
                if(i%2!=0){
                    arr[j]->RChild=p;
                }
            }
        }
    }
}

//先序递归遍历
void PreOrderTraverse(BiTree T)
{
    if(T==NULL){
        return;
    }
    printf("%c ",T->data);
    PreOrderTraverse(T->LChild);
    PreOrderTraverse(T->RChild);
}


//中序递归遍历
void InOrderTraverse(BiTree T)
{
    if(T==NULL){
        return;
    }
    InOrderTraverse(T->LChild);
    printf("%c ",T->data);
    InOrderTraverse(T->RChild);
}

//后序递归遍历
void PostOrderTraverse(BiTree T)
{
    if(T==NULL){
        return;
    }
    PostOrderTraverse(T->LChild);
    PostOrderTraverse(T->RChild);
    printf("%c ",T->data);
}

//层次遍历
/*构建队列*/
int front=0,rear=0;
void EnQueue(BiTree *t,BiTree node)
{//结点入队
    if(rear==MAX_SIZE){
        exit(0);
    }
    t[rear++]=node;
}
BiTNode* DeQueue(BiTree *t)
{//结点出队
    if(front==rear){
        exit(0);
    }
    return t[front++];
}
void LevelOrderTraverse(BiTree T)
{
    if(T){
        BiTree t[MAX_SIZE]={0};
        BiTNode *p=NULL;
        p=T;
        EnQueue(t,p);
        while(front<rear)
        {
            p=DeQueue(t);
            printf("%c ",p->data);
            if(p->LChild){
                EnQueue(t,p->LChild);
            }
            if(p->RChild){
                EnQueue(t,p->RChild);
            }
        }
    }
}

//求二叉树的深度
int BiTreeDepth(BiTree T)
{
    int left=0,right=0;
    if(!T){
        return 0;
    }
    if(T->LChild){
        left=BiTreeDepth(T->LChild);
    }
    if(T->RChild){
        right=BiTreeDepth(T->RChild);
    }
    return left>right?left+1:right+1;
}

//求叶子结点数
int Count_Leaves(BiTree T)
{
    if(!T){
        return 0;
    }
    if(!(T->LChild)&&!(T->RChild)){
        return 1;
    }
    return Count_Leaves(T->LChild)+Count_Leaves(T->RChild);
}


//先序非递归遍历
void PreOrderTraverse2(BiTree T)
{
    if(!T)
    {
        return;
    }
    //创建一个数组来模拟栈
    BiTree stack[MAX_SIZE]={0};
    int top=-1;
    stack[++top]=T;
    while(top>-1){
       BiTree node=stack[top--];
        printf("%c ",node->data);
        if(node->RChild){stack[++top]=node->RChild;}
        if(node->LChild){stack[++top]=node->LChild;}
    }
}

//中序非递归遍历
void InOrderTraverse2(BiTree T)
{
    if(!T){
        return;
    }
    BiTree stack[MAX_SIZE]={0};
    int top=-1;
    BiTree node=T;
    while(top>-1||node!=NULL){
        while(node!=NULL){//一直深入左节点
            stack[++top]=node;
            node=node->LChild;
        }
        node=stack[top--];
        printf("%c ",node->data);
        node=node->RChild;
    }
}

//后序非递归遍历
void PostOrderTraverse2(BiTree T)
{
     if(!T){
        return;
     }
     BiTree stack1[MAX_SIZE]={0};
     BiTree stack2[MAX_SIZE]={0};
     int top1=-1;
     int top2=-1;
     BiTree node=T;
     stack1[++top1]=node;
     while(top1>-1){
        node=stack1[top1--];
        stack2[++top2]=node;
        if(node->LChild!=NULL){stack1[++top1]=node->LChild;}
        if(node->RChild!=NULL){stack1[++top1]=node->RChild;}
    }
    while(top2>-1){
        printf("%c ",stack2[top2--]->data);
    }
}

/*=======================================================================*/


//先序线索化二叉树
BiTree pre=NULL;// 全局变量,用于记录前驱节点
void PreOrder_Threading(BiTree T)
{
    if(T==NULL){return;}
    if(T->LChild ==NULL){
        T->Ltag=1;
        T->LChild=pre;//Ltag为1,指向前驱
    }
    if(pre!=NULL && pre->RChild==NULL){
        pre->Rtag=1;
        pre->RChild=T;//Rtag为1,指向后继
    }
    pre=T;
    if(T->Ltag==0){PreOrder_Threading(T->LChild);}
    if(T->Rtag==0){PreOrder_Threading(T->RChild);}
}

//先序线索化后遍历
void PreOrder_Threading_Traverse(BiTree T)
{
    BiTree temp=T;
    while(temp!=NULL){
        printf("%c ",temp->data);
        if(temp->Ltag==0){
            temp=temp->LChild;
        }else
        {
            temp=temp->RChild;//寻找后继
        }
    }
}

/*=======================================================================*/

//中序线索化二叉树
BiTree pre2=NULL;// 全局变量,用于记录前驱节点
void InOrder_Threading(BiTree T)
{
    if(T==NULL){return;}

    if(T->Ltag==0){InOrder_Threading(T->LChild);}//深入到树的最左边的结点
    if(T->LChild ==NULL){
        T->Ltag=1;
        T->LChild=pre2;//Ltag为1,指向前驱
    }
    if(pre2!=NULL && pre2->RChild==NULL){
        pre2->Rtag=1;
        pre2->RChild=T;//Rtag为1,指向后继
    }
    pre2=T;
    if(T->Rtag==0){InOrder_Threading(T->RChild);}
}

//中序线索化后遍历
void InOrder_Threading_Traverse(BiTree T)
{
    BiTree p=T;
    while(p){
        while(p->Ltag==0){
            p=p->LChild;
        }//深入到最左边的结点
        printf("%c ",p->data);
        while(p->Rtag==1&&p->RChild!=NULL){
            //p->RChild!=NULL说明不是最后一个结点,这个接地那没有后继,指向NULL
            p=p->RChild;//找到后继节点
            printf("%c ",p->data);
        }
        p=p->RChild;
    }
}

/*=======================================================================*/

int main()
{
    BiTree T;
    int flag;
    printf("请输入需要的创建方式(1为先序,2为满二叉):");
    scanf("%d",&flag);
    switch(flag)
    {
    case 1://先序创建这棵树
        printf("按先序方式创建这棵树pre_T('#'表示空):\n");
        PreCreateBiTree(&T);
        printf("成功.\n");
        break;
    case 2://按满二叉树方式创建
        printf("按满二叉树方式创建这棵树full_T(以 1 A 为输入0结束例):\n");
        FullCreateBiTree(&T);
        printf("成功.\n");
        break;
    default:
        printf("你输入的序号有误.\n");
        break;
    }

    //递归遍历(三种:前中后)
    printf("先序递归的结果:");
    PreOrderTraverse(T);
    printf("\n");
    printf("成功.\n");
    printf("中序递归的结果:");
    InOrderTraverse(T);
    printf("\n");
    printf("成功.\n");
    printf("后序递归的结果:");
    PostOrderTraverse(T);
    printf("\n");
    printf("成功.\n");

    //非递归遍历(三种:前中后)
    printf("先序非递归的结果:");
    PreOrderTraverse2(T);
    printf("\n");
    printf("成功.\n");
    printf("中序非递归的结果:");
    InOrderTraverse2(T);
    printf("\n");
    printf("成功.\n");
    printf("后序非递归的结果:");
    PostOrderTraverse2(T);
    printf("\n");
    printf("成功.\n");


    //层次遍历
    printf("层序遍历的结果:");
    LevelOrderTraverse(T);
    printf("\n");
    printf("成功.\n");


    //求叶子结点数
    printf("这棵树的叶子结点数为:%d.\n",Count_Leaves(T));
    //求二叉树的深度
    printf("这棵树的深度为:%d.\n",BiTreeDepth(T));

    printf("================\n");
    printf("1、先序线索化.\n");
    printf("2、中序线索化.\n");
    printf("请输入需要线索化的形式:");
    int flag2;
    scanf("%d",&flag2);
    switch(flag2)
    {
        case 1:
            //先序线索化二叉树并遍历
            PreOrder_Threading(T);
            printf("先序线索化二叉树并遍历,结果为:");
            PreOrder_Threading_Traverse(T);
            break;
        case 2:
            //中序线索化二叉树并遍历
            InOrder_Threading(T);
            printf("中序线索化二叉树并遍历,结果为:");
            InOrder_Threading_Traverse(T);
            break;
        default:
            printf("你输入的序号有误.\n");
            break;
    }
    return 0;
}

运行截图

image-20230530141756319

🚀先看后赞,养成习惯!🚀

🚀 先看后赞,养成习惯!🚀

🎈觉得文章写得不错的老铁们,点赞评论关注走一波!谢谢啦!🎈


  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值