大家好,我是Johngo!
今天有在校的粉丝想要C语言实现的树的后续遍历的详细讲解,今天就来看看。
后面给到了所有的代码,可以直接运行!
二叉树后序遍历
二叉树的遍历方式主要由先序遍历、中序遍历和后续遍历,还后就是层次遍历
感受完前两篇的遍历方式,本节来看看后序遍历
后序遍历过程
a. 先序遍历其左子树;
b. 先序遍历其右子树;
c. 访问根节点;
然后就是一直递归下去,在访问到节点的时候,可以进行节点的相关处理,比如说简单的访问节点值
下图是一棵二叉树,我们来手动模拟一下后序遍历过程
按照上述后序遍历的过程,得到后序遍历序列:
H I D E B F G C A
递归实现
二叉树的后序遍历利用上述的递归思想进行C语言代码实现:
树形结构按照上述树形结构进行初始化
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# define ElementType char
//结点结构体
typedef struct BinTNode{
ElementType data;
struct BinTNode * left;
struct BinTNode * right;
}BinTNode, *BinTree;
// 初始化树形结构
BinTNode * CreateBiTree(BinTNode *T){
T=(BinTNode*)malloc(sizeof(BinTNode));
T->data='A';
T->left=(BinTNode*)malloc(sizeof(BinTNode));
T->left->data='B';
T->right=(BinTNode*)malloc(sizeof(BinTNode));
T->right->data='C';
T->left->left=(BinTNode*)malloc(sizeof(BinTNode));
T->left->left->data='D';
T->left->right=(BinTNode*)malloc(sizeof(BinTNode));
T->left->right->data='E';
T->left->right->left=NULL;
T->left->right->right=NULL;
T->left->left->left=(BinTNode*)malloc(sizeof(BinTNode));
T->left->left->left->data='H';
T->left->left->left->left=NULL;
T->left->left->left->right=NULL;
T->left->left->right=(BinTNode*)malloc(sizeof(BinTNode));
T->left->left->right->data='I';
T->left->left->right->left=NULL;
T->left->left->right->right=NULL;
T->right->left=(BinTNode*)malloc(sizeof(BinTNode));
T->right->left->data='F';
T->right->left->left=NULL;
T->right->left->right=NULL;
T->right->right=(BinTNode*)malloc(sizeof(BinTNode));
T->right->right->data='G';
T->right->right->left=NULL;
T->right->right->right=NULL;
return T;
}
// 遍历过程中,输出节点值
void printElement(BinTNode * T){
printf("%c ",T->data);
}
//先序遍历
void PostOrderTraverse(BinTNode * T){
if (T) {
PostOrderTraverse(T->left); //递归访问左孩子
PostOrderTraverse(T->right); //递归访问右孩子
printElement(T); //输出节点值
}
// 当节点为空的时候,返回
return;
}
int main() {
BinTNode * Tree;
Tree = CreateBiTree(Tree); // 初始化树形结构
printf("后序遍历: ");
PostOrderTraverse(Tree); // 先序递归进行
printf("\n"); // 最后换行
return 0;
}
运行结果:
后序遍历: H I D E B F G C A
非递归实现
相比于之前的先序遍历和中序遍历非递归实现,后序遍历的非递归算法与之前有所不同,后续遍历需要先访问左右子结点后,才能访问该结点,而这也是非递归的难点所在。
考虑了几种实现的方案,这里我给出我认为比较清晰的一个方案供大家参考:借助两个栈(S1和S2)来进行操作
看下面伪代码:
初始化S1的top元素是树的根结点;
while(top1 != -1) {
将栈顶元素push到S2;
if(栈顶元素有孩子结点){
按照孩子结点的左右顺序push进S1;
}
}
循环逐个弹出S2的栈顶元素
伪代码可能看了之后有些不太好懂,但是还算看着清晰吧,下面借助图,一定会思路清晰的(长图发放):
有了这个思路就应该会很清晰了,下面按照上述思路用C语言实现:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define ElementType char
int top_S1 = -1;