(文章篇幅有点长,二叉树的递归遍历算法不作详细分析,但是二叉树的非递归遍历算法和层次遍历算法都有非常详细的分析过程,记得往下翻哦!)
二叉树的递归遍历算法实现
我们首先用递归的方法先序遍历创建这样一棵二叉树,如图所示,二叉树创建完毕,我们开始研究二叉树的非递归遍历算法。
1. 算法代码如下:
#include<stdio.h>
#include<stdlib.h>
#define maxsize 1000
typedef char elemtype;
typedef struct BiTreeNode
{
elemtype data;
struct BiTreeNode* LChild, * RChild;
}BiTreeNode,*BiTree;
BiTree creat_BiTree()
{
char ch;
BiTree T;
scanf_s("%c", &ch);
if (ch == '#')
{
T= NULL;
}
else
{
T = (BiTreeNode*)malloc(sizeof(BiTreeNode));
T->data = ch;
T->LChild = creat_BiTree();
T->RChild = creat_BiTree();
}
return T;
}
//先序遍历
int PreOrder(BiTree pointer)
{
if (pointer == NULL)
return 0;
printf("%c", pointer->data);
PreOrder(pointer->LChild);
PreOrder(pointer->RChild);
}
//中序遍历
int InOrder(BiTree pointer)
{
if (pointer == NULL)
return 0;
InOrder(pointer->LChild);
printf("%c", pointer->data);
InOrder(pointer->RChild);
}
//后序遍历
int PostOrder(BiTree pointer)
{
if (pointer == NULL)
return 0;
PostOrder(pointer->LChild);
PostOrder(pointer->RChild);
printf("%c", pointer->data);
}
//二叉树的层次遍历
int Levelprint(BiTree pointer)
{
if (pointer == NULL)
return 0;
BiTree a[maxsize];
int front = -1;
int rear = 0;
BiTreeNode* p = pointer;
a[rear] = p;
while (front != rear)
{
front++;
printf("%c", a[front]->data);
if (a[front]->LChild != NULL)
{
rear++;
a[rear] = a[front]->LChild;
}
if (a[front]->RChild != NULL)
{
rear++;
a[rear] = a[front]->RChild;
}
}
return 1;
}
//统计二叉树的结点数
int PreOrder2(BiTree pointer,int *count)
{
if (pointer == NULL) return 0;
(*count)++;
PreOrder2(pointer->LChild, count);
PreOrder2(pointer->RChild, count);
}
//统计二叉树非终端结点(分支结点)的个数
int PreOrder3(BiTree pointer, int* count)
{
if (pointer == NULL) return 0;
if (pointer->LChild != NULL||pointer->RChild != NULL)
{
(*count)++;
}
PreOrder3(pointer->LChild, count);
PreOrder3(pointer->RChild, count);
}
//统计二叉树的叶子结点的个数
int PreOrder4(BiTree pointer, int* count)
{
if (pointer == NULL) return 0;
if (!pointer->LChild&&!pointer->RChild)
{
(*count)++;
}
PreOrder4(pointer->LChild, count);
PreOrder4(pointer->RChild, count);
}
//求二叉树的高度
int BiTree_height(BiTree pointer)
{
int LHeight, RHeight, Tree_Height;
if (pointer == NULL) return 0;
LHeight = BiTree_height(pointer->LChild);
RHeight = BiTree_height(pointer->RChild);
Tree_Height = (LHeight > RHeight) ? LHeight + 1 : RHeight + 1;
return Tree_Height;
}
void main()
{
BiTree T;
int count1 = 0,count2=0,count3=0,count4=0;
T = creat_BiTree();
printf("先序遍历序列:\n");
PreOrder(T);
printf("\n中序遍历序列:\n");
InOrder(T);
printf("\n后序遍历序列:\n");
PostOrder(T);
printf("\n层次遍历序列:\n");
Levelprint(T);
printf("\n二叉树的结点数为:\n");
PreOrder2(T, &count1);
printf("%d", count1);
printf("\n二叉树的分支结点数为:\n");
PreOrder3(T, &count2);
printf("%d", count2);
printf("\n二叉树的叶子结点数为:\n");
PreOrder4(T, &count3);
printf("%d", count3);
printf("\n二叉树的高度为:\n");
count4 = BiTree_height(T);
printf("%d", count4);
}
2. 代码运行结果:
二叉树的非递归遍历算法实现
我们首先用递归的方法先序遍历创建这样一棵二叉树,如图所示,二叉树创建完毕,我们开始研究二叉树的非递归遍历算法。
一、非递归先序遍历算法
1.算法实现思路:
二叉树的先序遍历算法主要思想是:访问根结点,先序遍历左子树,先序遍历右子树。我们可以使用一个栈来实现二叉树的非递归先序遍历算法。首先,创建栈S并对其初始化,栈中的每一个元素是二叉树中的结点。定义指针p开始指向根结点,从根结点开始遍历二叉树中的结点,若结点存在(P!=NULL),输出该结点的值,并将该结点入栈S中,将指针p指向其左孩子(P=P->Lchild),之后判断P指向的结点是否为空,若为空,则从栈中弹出上一结点,并让指针P指向该结点的右孩子( p=pop(s),p = p->RChild),用一个while循环重复以上步骤。直到结点不存在且栈为空结束时循环 while(p || !isempty(s)),二叉树先序遍历遍历结束。
2.算法代码如下:
#include<stdio.h>
#include<stdlib.h>
#define maxsize 100
typedef char elemtype;
typedef struct BiTreeNode
{
elemtype data;
struct BiTreeNode* LChild, * RChild;
}BiTreeNode, * BiTree;
typedef struct stack
{
BiTreeNode* a[maxsize];
int top;
}sqstack;
sqstack* initialize()
{
sqstack* s;
s = (sqstack*)malloc(sizeof(sqstack));
if (!s)
return NULL;
else
{
s->top = -1;
return s;
}
}
int isempty(sqstack* s)
{
return (s->top == -1);
}
int isfull(sqstack* s)
{
return (s->top == maxsize - 1);
}
int push(sqstack* s, BiTreeNode* p)
{
if (isfull(s))
return 0;
else
s->a[++(s->top)] = p;
return 1;
}
BiTreeNode* pop(sqstack* s)
{
return s->a[(s->top)--];
}
//以递归的方式先序创建一棵二叉树
BiTree CreatBiTree()
{
char ch;
BiTree T;
scanf_s("%c", &ch);
if (ch == '#') T = NULL;
else
{
T = (BiTree)malloc(sizeof(BiTreeNode));
T->data = ch;
T->LChild = CreatBiTree();
T->RChild = CreatBiTree();
}
return T;
}
//二叉树的非递归先序遍历
void Non_recursive_PREprint(BiTree pointer)
{
sqstack* s;
s = initialize();
BiTreeNode* p;
p = pointer;
while (p || !isempty(s))
{
if (p != NULL)
{
printf("%c", p->data);
push(s, p);
p = p->LChild;
}
else
{
p = pop(s);
p = p->RChild;
}
}
printf("\n");
}
void main()
{
BiTree T;
T = CreatBiTree();
printf("二叉树的先序遍历:\n");
Non_recursive_PREprint(T);
}
3.代码运行结果
二、非递归中序遍历算法
1.算法思路:
二叉树的中遍历算法主要思想是:中序遍历左子树,访问根结点,中序遍历右子树。该遍历算法与先序遍历算法思路相似,同样使用一个栈来实现二叉树的非递归中遍历算法。首先,创建栈S并对其初始化,栈中的每一个元素是二叉树中的结点。定义指针p开始指向根结点,从根结点开始遍历二叉树中的结点,若结点存在(P!=NULL),将该结点入栈S中,将指针p指向其左孩子(P=P->Lchild),之后判断P指向的结点是否为空,若为空,则从栈中弹出上一结点,并输出该结点的值,并让指针P指向该结点的右孩子( p=pop(s);printf(“%c”,p->data);p = p->RChild),用一个while循环重复以上步骤。直到结点不存在且栈为空结束时循环 while(p || !isempty(s)),二叉树中序遍历算法结束。
2.算法代码如下:
#include<stdio.h>
#include<stdlib.h>
#define maxsize 100
typedef char elemtype;
typedef struct BiTreeNode
{
elemtype data;
struct BiTreeNode* LChild, * RChild;
}BiTreeNode, * BiTree;
typedef struct stack
{
BiTreeNode* a[maxsize];
int top;
}sqstack;
sqstack* initialize()
{
sqstack* s;
s = (sqstack*)malloc(sizeof(sqstack));
if (!s)
return NULL;
else
{
s->top = -1;
return s;
}
}
int isempty(sqstack* s)
{
return (s->top == -1);
}
int isfull(sqstack* s)
{
return (s->top == maxsize - 1);
}
int push(sqstack* s, BiTreeNode* p)
{
if (isfull(s))
return 0;
else
s->a[++(s->top)] = p;
return 1;
}
BiTreeNode* pop(sqstack* s)
{
return s->a[(s->top)--];
}
//以递归的方式先序创建一棵二叉树
BiTree CreatBiTree()
{
char ch;
BiTree T;
scanf_s("%c", &ch);
if (ch == '#') T = NULL;
else
{
T = (BiTree)malloc(sizeof(BiTreeNode));
T->data = ch;
T->LChild = CreatBiTree();
T->RChild = CreatBiTree();
}
return T;
}
//二叉树的非递归中序遍历
void Non_recursive_INprint(BiTree pointer)
{
sqstack* s;
s = initialize();
BiTreeNode* p;
p = pointer;
while (p || !isempty(s))
{
if (p != NULL)
{
push(s, p);
p = p->LChild;
}
else
{
p = pop(s);
printf("%c", p->data);
p = p->RChild;
}
}
printf("\n");
}
void main()
{
BiTree T;
T = CreatBiTree();
printf("二叉树的中序遍历:\n");
Non_recursive_INprint(T);
}
3.代码运行结果:
三、非递归后序遍历算法
1.算法思路:
二叉树的后序遍历算法的主要思想是:后序遍历左子树,后序遍历右子树,访问根结点。二叉树的非递归后序遍历算法可以构造一栈来实现,栈中的元素存储的是二叉树中的结点,对于后序遍历算法,我们需要判断二叉树中每个结点的左子树是否遍历完,只有将左子树遍历完,我们才能对该结点的右子树和该结点进行遍历输出,我们可以定义一个标志数组int temp[maxsize],先初始化为0,数组元素和栈s中元素对应,栈顶指针top和数组下标对应。首先,先让指针p指向这棵二叉树的根结点,将该结点压入栈s中,同时对其标志数组赋值为0 (tem[s->top]=0),将指针p指向该结点的左孩子(p=p->Lchild),如果其左孩子为空,将栈s的栈顶元素出栈,指针p指向其右孩子,同时将该结点压回栈s中,同时对其标志数组赋值为1 (tem[s->top]=1),表示该结点的左子树已遍历完成, 若该结点的右孩子为空,则对堆栈结点进行遍历,将标志数组tem[s->top]值为1的结点全部打印输出。从二叉树的根结点开始,定一个外部循环,不断重复以上对结点的操作,直到指针p指向的结点为空且栈s中元素为空时结束循环。这就是非递归后续遍历二叉树的主要思路。
2.算法代码如下:
#include<stdio.h>
#include<stdlib.h>
#define maxsize 100
typedef char elemtype;
typedef struct BiTreeNode
{
elemtype data;
struct BiTreeNode* LChild, * RChild;
}BiTreeNode, * BiTree;
typedef struct stack
{
BiTreeNode* a[maxsize];
int top;
}sqstack;
sqstack* initialize()
{
sqstack* s;
s = (sqstack*)malloc(sizeof(sqstack));
if (!s)
return NULL;
else
{
s->top = -1;
return s;
}
}
int isempty(sqstack* s)
{
return (s->top == -1);
}
int isfull(sqstack* s)
{
return (s->top == maxsize - 1);
}
int push(sqstack* s, BiTreeNode* p)
{
if (isfull(s))
return 0;
else
s->a[++(s->top)] = p;
return 1;
}
BiTreeNode* pop(sqstack* s)
{
return s->a[(s->top)--];
}
//以递归的方式先序创建一棵二叉树
BiTree CreatBiTree()
{
char ch;
BiTree T;
scanf_s("%c", &ch);
if (ch == '#') T = NULL;
else
{
T = (BiTree)malloc(sizeof(BiTreeNode));
T->data = ch;
T->LChild = CreatBiTree();
T->RChild = CreatBiTree();
}
return T;
}
//二叉树的非递归后序遍历
void Non_recursive_POSTprint(BiTree pointer)
{
sqstack* s;
s = initialize();
BiTreeNode* p = pointer;
int temp[maxsize] = {
0 };
while (p || !isempty(s))
{
if (p != NULL)
{
push(s, p);
temp[s->top] = 0;
p = p->LChild;
}
else
{
while (temp[s->top] == 1)
{
p = pop(s);
printf("%c", p->data);
}
if (s->top == -1)
{
break;
}
p = pop(s);
push(s, p);
temp[s->top] = 1;
p = p->RChild;
}
}
printf("\n");
}
void main()
{
BiTree T;
T = CreatBiTree();
printf("二叉树的后序遍历: ");
Non_recursive_POSTprint(T);
}
3.代码运行结果:
四、二叉树的层次遍历算法
1.算法思路:
二叉树的层次遍历算法是指从二叉树的第一层开始,逐层从左到右依次遍历结点,最终将整棵二叉树遍历完成。对于这个算法,我们可以采用队列来实现,我们初始化一个顺序队列,顺序队列的每个元素都存储着二叉树的结点,开始顺序队列为空,首先,将根结点入队,进入循环,将队头指针所指的元素出队,并输出其结点的值,如果该结点的左孩子存在,则将其左孩子入队,如果该结点的右孩子存在,则将右孩子入队,直到队头指针和队尾指针相等时(表明队列为空)退出循环,这颗二叉树的层次遍历就完成了。
2.算法代码如下:
#include<stdio.h>
#include<stdlib.h>
#define maxsize 100
typedef char elemtype;
typedef struct BiTreeNode
{
elemtype data;
struct BiTreeNode* LChild, * RChild;
}BiTreeNode, * BiTree;
typedef struct stack
{
BiTreeNode* a[maxsize];
int top;
}sqstack;
sqstack* initialize()
{
sqstack* s;
s = (sqstack*)malloc(sizeof(sqstack));
if (!s)
return NULL;
else
{
s->top = -1;
return s;
}
}
int isempty(sqstack* s)
{
return (s->top == -1);
}
int isfull(sqstack* s)
{
return (s->top == maxsize - 1);
}
int push(sqstack* s, BiTreeNode* p)
{
if (isfull(s))
return 0;
else
s->a[++(s->top)] = p;
return 1;
}
BiTreeNode* pop(sqstack* s)
{
return s->a[(s->top)--];
}
//以递归的方式先序创建一棵二叉树
BiTree CreatBiTree()
{
char ch;
BiTree T;
scanf_s("%c", &ch);
if (ch == '#') T = NULL;
else
{
T = (BiTree)malloc(sizeof(BiTreeNode));
T->data = ch;
T->LChild = CreatBiTree();
T->RChild = CreatBiTree();
}
return T;
}
//二叉树的层次遍历
int Levelprint(BiTree pointer)
{
if (pointer == NULL)
return 0;
BiTree a[maxsize];
int front = -1;
int rear = 0;
BiTreeNode* p = pointer;
a[rear] = p;
while (front != rear)
{
front++;
printf("%c", a[front]->data);
if (a[front]->LChild != NULL)
{
rear++;
a[rear] = a[front]->LChild;
}
if (a[front]->RChild != NULL)
{
rear++;
a[rear] = a[front]->RChild;
}
}
return 1;
}
void main()
{
BiTree T;
T = CreatBiTree();
printf("二叉树的层次遍历为: ");
Levelprint(T);
}
3.代码运行结果: