文章目录
- ⭐️写在前面的话⭐️
- 二叉树的一些基本操作
- 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;
}
运行截图
🚀先看后赞,养成习惯!🚀
🚀 先看后赞,养成习惯!🚀
🎈觉得文章写得不错的老铁们,点赞评论关注走一波!谢谢啦!🎈