文章目录
- ⭐️写在前面的话⭐️
- 二叉树的一些基本操作
- 1、结构定义
- 2、先序创建这棵树
- 3、按满二叉树方式创建
- 4、三种递归遍历
- 5、层次遍历
- 6、求二叉树的深度
- 7、求叶子结点数
- 8、三种非递归遍历
- 9、先序线索化二叉树
- 10、先序线索化后遍历
- 11、中序线索化二叉树
- 12、中序线索化后遍历
- 主函数
 
- 程序源码
- 运行截图
 
⭐️写在前面的话⭐️
📒博客主页: 程序员好冰
🎉欢迎 【点赞👍 关注🔎 收藏⭐️ 留言📝】
📌本文由 程序员好冰 原创,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;
}
运行截图
 
 
🚀先看后赞,养成习惯!🚀
🚀 先看后赞,养成习惯!🚀
🎈觉得文章写得不错的老铁们,点赞评论关注走一波!谢谢啦!🎈
















