二叉树的建立和遍历及求二叉树的深度
首先就说一说二叉树的建立(二叉链表)
我们需要一个先建立一个结构体来做为其结点的数据结构,其数据域用来存放结点的数值,俩个指针域分别存放其左孩子和右孩子。接下来是建立方式,我们使用先序扩展序列来建立,后台输入为一串字符,字符满足要建二叉树的先序序列,其中孩子为空的地方我们用#来表示,代码如下:
BiTree CreateBiTree()
{
BiTree bt = NULL;
char ch;
ch = getchar();
if (ch == '#')
bt = NULL;
else
{
bt = (BiTree)malloc(sizeof(BiTNode));
bt->data = ch;
bt->LChild = CreateBiTree();
bt->RChild = CreateBiTree();
}
return bt;
}
接下来我们说一说如何遍历这个二叉树
二叉树的遍历一般来说有三种,分为前中后序遍历,每种遍历又可以分为俩种方式来遍历,递归或者非递归。递归比较简单易懂,我就直接上代码块,如下:
void PreOrder(BiTree root)
{
if (root)
{
printf("%c", root->data);
PreOrder(root->LChild); //前序
PreOrder(root->RChild);
}
}
void InOrder(BiTree root)
{
if (root)
{
InOrder(root->LChild);
printf("%c", root->data); //中序
InOrder(root->RChild);
}
}
void PostOrder(BiTree root)
{
if (root)
{
PostOrder(root->LChild);
PostOrder(root->RChild); //后序
printf("%c", root->data);
}
}
我们主要来讲一讲非递归实现遍历的方法,我们以后序非递归为例,我们需要用栈这个数据结构来对树的结点进行回溯,算法思路就是首先拿到根节点,然后一直向左孩子方向压栈,直到左子树的左孩子为空为止,然后判断栈是否为空,如果不为空,然后取出栈顶元素,判断栈顶的右孩子是否为空,如果为空则访问当前节点,如果右孩子不为空,则将当前节点指向它的右孩子,然后再进行下一次循环,我们会发现这样的代码会产生一个问题,就是假如你刚刚把右孩子访问完,再退会上一层,那它右孩子肯定不为空,又会进入它的右孩子,所以我们应该在代码中加一个变量,用变量来记录它是否进入过右孩子,这样可以防止重复访问的问题,下面我们来看看代码
void PostOrderTwo(BiTree root)
{
SeqStack s = start();
BiTree p,q;
p = root;
q = NULL;
while(p!=NULL || isEmpty(s))
{
while(p!=NULL)
{
Push(s,p);
p = p->LChild;
}
if(isEmpty(s))
{
p = Top(s);
if(p->RChild==NULL || p->RChild==q)
{
p = Pop(s);
visit(p);
q=p;
p=NULL;
}
else
p=p->RChild;
}
}
}
完整的建立和先中后序遍历代码如下:
在这里插入代码#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
#define max 1000
typedef struct cat
{
char data;
struct cat *LChild;
struct cat *RChild;
} BiTNode,*BiTree;
typedef struct dog
{
BiTree p[max];
int top;
}*SeqStack,stack;
SeqStack start()
{
SeqStack s;
s = (SeqStack)malloc(sizeof(stack));
s->top = -1;
return s;
}
BiTree Pop(SeqStack s)
{
BiTree a = s->p[s->top];
s->top--;
return a;
}
int isEmpty(SeqStack s)
{
if(s->top==-1){
return 0;
}else{
return 1;
}
}
BiTree Top(SeqStack s)
{
return s->p[s->top];
}
void visit(BiTree b)
{
printf("%c",b->data);
}
void Push(SeqStack s,BiTree b)
{
(s->top)++;
s->p[s->top] = b;
}
BiTree CreateBiTree()
{
BiTree bt = NULL;
char ch;
ch = getchar();
if (ch == '#')
bt = NULL;
else
{
bt = (BiTree)malloc(sizeof(BiTNode));
bt->data = ch;
bt->LChild = CreateBiTree();
bt->RChild = CreateBiTree();
}
return bt;
}
void PreOrder(BiTree root)
{
if (root)
{
printf("%c", root->data);
PreOrder(root->LChild);
PreOrder(root->RChild);
}
}
void InOrder(BiTree root)
{
if (root)
{
InOrder(root->LChild);
printf("%c", root->data);
InOrder(root->RChild);
}
}
void PostOrder(BiTree root)
{
if (root)
{
PostOrder(root->LChild);
PostOrder(root->RChild);
printf("%c", root->data);
}
}
void PostOrderTwo(BiTree root)
{
SeqStack s = start();
BiTree p,q;
p = root;
q = NULL;
while(p!=NULL || isEmpty(s))
{
while(p!=NULL)
{
Push(s,p);
p = p->LChild;
}
if(isEmpty(s))
{
p = Top(s);
if(p->RChild==NULL || p->RChild==q)
{
p = Pop(s);
visit(p);
q=p;
p=NULL;
}
else
p=p->RChild;
}
}
}
int main()
{
BiTree bt = NULL;
bt = CreateBiTree();
PreOrder(bt);
printf("\n");
InOrder(bt);
printf("\n");
PostOrderTwo(bt);
return 0;
}
下面我们说一说求二叉树深度的方法
其实求深度还是相当于是要遍历这个二叉树,只不过是把每次访问计数为M,然后俩颗子树各自的M的最大值加一即为该二叉树的深度,之所以加一是它的根结点也算一层。
实现代码如下:
在这里插入代码片#include<stdio.h>
#include<stdlib.h>
#include<malloc.h>
typedef struct cat
{
char data;
struct cat *LChild;
struct cat *RChild;
} BiTNode,*BiTree;
BiTree CreateBiTree()
{
BiTree bt = NULL;
char ch;
ch = getchar();
if (ch == '#')
bt = NULL;
else
{
bt = (BiTree)malloc(sizeof(BiTNode));
bt->data = ch;
bt->LChild = CreateBiTree();
bt->RChild = CreateBiTree();
}
return bt;
}
int PreOrder(BiTree root)
{
if (root)
{
int a = PreOrder(root->LChild);
int b = PreOrder(root->RChild);
if(a>b){
return a+1;
}else{
return b+1;
}
}
return 0;
}
int main()
{
BiTree bt = NULL;
bt = CreateBiTree();
int max = PreOrder(bt);
printf("%d",max);
return 0;
}
如果对代码有疑问或者发现bug请联系作者qq1748708966.