数据结构学习-二叉树的基本操作
最近在学习数据结构中的二叉树,想把一些基本操作用C语言实现之后整理一下
主要内容包括
1.二叉树数据结构类型定义:二叉链表
2.按照输入的先序序列建立二叉树,其中#代表空
3.按先序后序中序遍历二叉树(递归)
4.按先序后序中序遍历二叉树(非递归)
5.给定二叉树的后序和中序序列,构造二叉树
6.递归求取二叉树的最大路径和
7.翻转二叉树
8.求二叉树的繁荣度(高度x宽度)
一.二叉树数据结构类型定义:二叉链表
#define ElementType char//元素类型宏定义
typedef struct Bnode//二叉树数据结构类型宏定义:二叉链表
{
ElementType data;
struct Bnode *left;
struct Bnode *right;
}BinTree;
typedef Bintree * BT;
二.按照输入的先序序列建立二叉树,其中#代表空
BT CreatBinTreeByPreOrder()
{
ElementType ch;
BT node;
scanf("%c",&ch);
if(ch=='#')return 0;
else
{
node=(BT)malloc(sizeof(struct Bnode));
node->data=ch;
node->left=CreatBinTreeByPreOrder();
node->right=CreatBinTreeByPreOrder();
}
return node;
}
三.按先序后序中序遍历二叉树(递归)
void InorderTraversal( BT root )
{
if(!root)return ;
else
{
InorderTraversal(root->left);
printf("%c",root->data);
InorderTraversal(root->right);
}
}
void PreorderTraversal( BinTree BT )
{
if(!root)return ;
else
{
printf("%c",root->data);
InorderTraversal(root->left);
InorderTraversal(root->right);
}
}
void PostorderTraversal( BinTree BT )
{
if(!root)return ;
else
{
InorderTraversal(root->left);
InorderTraversal(root->right);
printf("%c",root->data);
}
}
四.按先序后序中序遍历二叉树(非递归)
这里主要是运用了栈的思想,栈的c语言数据结构定义和基本操作就不列出来了,主要阐述二叉树遍历的算法,而其中的先序和中序遍历相对于后序遍历来说更为简单,故只列出后序遍历的非递归算法
/*后序遍历的非递归算法*/
void PostOrderTravel(BinTree BT)
{
if(!BT) return;//空树退出
Stack S;
push(S,BT);//根节点入栈
while(!IsEmpty(S)||BT)
{
if(BT)//从根节点一直向左找,不空就入栈,并标记该节点的右子树未被访问过
{
S->data[S->top].ptr=BT;
S->data[S->top].tag=0;
S->top++;
BT=BT->left;
}
else//找到最左端节点后看栈,若栈顶元素有右子树且未被访问,就去访问其右子树并标记访问过,否则退栈输出
{
BT=GetTop(S);//取栈顶结点
if(S->data[S->top].tag==0&&BT->right)
{
S->data[S->top].tag==1;
BT=BT->right;
}
else
{
printf("%d",S->data[S->top].ptr->data);
S->top--;
BT=NULL;
}
}
}
}
五.给定二叉树的后序和中序序列,构造二叉树,其中PS(IS)为子树后序(中序)序列的第一个元素位置 ,PE为最后一个位置
BT CreatBinTree(ElementType Post[],ElementType In[],int PS,int PE,int IS,int IE)
{
//如何判断给定序列能否建树?
if((PE-PS)!=(IE-IS))
return 0;//两序列长度不等不能建树
ElementType help[PE+1];
int i,j,flag;
for(i=0;i<PE+1;i++)//两序列中有字符不相等不能建树
help[i]=Post[i];
for(i=0;i<IE+1;i++)
{
flag=0;
for(j=0;j<PE+1;j++)
{
if(Post[j]==In[i])
{
flag=1;break;}
}
if(!flag) return 0;//序列不一致
}
int rlen=0,llen=0;
//找到后序序列的最后一个元素 为根
BT node=(BT)malloc(sizeof(struct Bnode));
node->data=Post[PE];
node->left=0;
node->right=0;
while(In[llen]!=Post[PE])
llen++;
rlen=IE-llen;
if(llen!=0)
node->left=CreatBinTree(Post,In,PS,PE-rlen-1,IS,llen-1);
if(rlen!=0)
node->right=CreatBinTree(Post,In,PE-rlen,PE-1,llen+1,IE);
return node;
}
六.递归求取二叉树的最大路径和
其中有个自定义max函数需要自己写
int maxPathSum(TreeNodePtr root, int sum) {
if(!root)return 0;
else return root->data+max(maxPathSum(root->left,sum),maxPathSum(root->right,sum));
}
七.翻转二叉树
BT invertTree(BT root) {
if(!root)return NULL;
BT lefttree=root->left;
root->left=root->right;
root->right=lefttree;
invertTree(root->left);
invertTree(root->right);
return root;
}
八.求二叉树的繁荣度
二叉树的繁荣度定义为二叉树的宽度(所有层中结点最多的层的节点数)乘上二叉树的高度,所以这个函数实现了求二叉树的高度和深度
基本思想是借助队列层序存储二叉树的每个结点,并给每个结点增加一个标记为该节点所在层数nodelev
#define MaxSize 50
#define MaxHeight 10
typedef struct
{
BT ptr;
int nodelev;
}WeightArray;
typedef struct
{
int rear;
int front;
WeightArray a[MaxSize];
}Queue;
int GetFlourishingDegree(BinTree BT)
{
Queue * Q=(Queue *)malloc(sizeof(Queue));//为队列分配空间
Q->front=0;
Q->rear=1;//rear始终指向队列最后一个元素的下一个位置
Q->a=(WeightArray *)malloc(MaxSize*sizeof(WeightArray));//为队列中的结构体数组分配空间
Q->a[front].ptr=BT;//树根结点入队
Q->a[front].nodelev=1;//根节点在第一层
while(front<rear)//当队列不空时
{
if(Q->a[front].ptr->left)//左子树进队
{
Q->a[rear].ptr=Q->a[front].ptr->left;
Q->a[rear].nodelev=Q->a[front].nodelev+1;
rear++;
}
if(Q->a[front].ptr->right)//右子树进队
{
Q->a[rear].ptr=Q->a[front].ptr->right;
Q->a[rear].nodelev=Q->a[front].nodelev+1;
rear++;
}
front++;//根出队
}
int i,height=1,maxlev[MaxHeight],weight=1;
for(i=0;i<rear;i++)//求树高
{
if(Q->a[i].nodelev>height)
height=Q->a[i].nodelev;
maxlev[Q->a[i].nodelev]++;
}
for(i=1;i<=height;i++)//求树宽
{
if(maxlev[i]>weight)
weight=maxlev[i];
}
return height*weight;
}
写在最后
本人大一萌新,初学数据结构与算法,上述代码大部分上机调试过,有什么bug欢迎评论区各路大佬指出。
新人创作实属不易,还请大家不要恶意抄袭,点赞再走,养成习惯,比芯♥