使用C语言对二叉树进行层次、前、中、后序遍历的递归和非递归代码
#include "stdio.h"
#include "stdlib.h"
#define N 10 // 一共10条数据
void prtArr(float *x, int size){
for (int i = 0; i < size; i++) printf("%.2f ", x[i]); printf("\n"); } // 打印数组
typedef struct TreeNode{
float val; struct TreeNode *left, *right;}TreeNode; // 定义二叉树结构
float * level_traversal(TreeNode *root, int size){
// 层次遍历,size表示节点总数
TreeNode **queue = (TreeNode **)malloc(sizeof(TreeNode*) * size); // queue 存储遍历的节点,保持顺序
float *arr = (float *)malloc(sizeof(float) * size); // arr 存储遍历结果
int front = 0, rear = 0, arridx = 0; // front, rear 分别是队列的头和尾。arridx 是遍历结果数组 的下标,从0开始。
queue[rear++] = root;
// 出队,获取节点值,入队左右子节点,直到队列为空
while (front < rear){
TreeNode *node = queue[front++]; arr[arridx++] = node->val; if (node->left) queue[rear++] = node->left; if (node->right) queue[rear++] = node->right; }
free(queue); return arr;
}
// 前序遍历, idx用于递归时确定下一个结果存放在结果数组什么位置
void pre_traversal_rec(TreeNode *root, float* arr, int* idx){
if (!root) return ; arr[(*idx)++] = root->val; pre_traversal_rec(root->left, arr, idx); pre_traversal_rec(root->right, arr, idx); }
void pre_traversal_nrec(TreeNode *root, float* arr, int size){
if (!root) return ; int top = -1, idx = 0; TreeNode **stack = (TreeNode **)malloc(sizeof(TreeNode*) * size); stack[++top] = root;
// 出栈,获取节点值,入栈右左子节点,直到栈为空
while (top >= 0){
TreeNode *node = stack[top--]; arr[idx++] = node->val; if (node->right) stack[++top] = node->right; if (node->left) stack[++top] = node->left; }
}
// 中序遍历
void in_traversal_rec(TreeNode *root, float *arr, int *idx){
if (!root) return ; in_traversal_rec(root->left, arr, idx); arr[(*idx)++] = root->val; in_traversal_rec(root->right, arr, idx); }
void in_traversal_nrec(TreeNode *root, float *arr, int size){
if (!root) return; int top = -1, idx = 0; TreeNode **stack = (TreeNode **)malloc(sizeof(TreeNode*) * size); TreeNode *cur = root;
// 1. 压栈的同时,将当前指针移动到最左边的节点。2. 出栈,获取节点值。 3. 将指针移动到右子节点。循环1-3直到栈为空。
while (top >=0 || cur){
while (cur) {
stack[++top] = cur; cur = cur->left; }
cur = stack[top--]; arr[idx++] = cur->val; cur = cur->right;
}
}
// 后序遍历
void post_traversal_rec(TreeNode *root, float *arr, int *idx){
if (!root) return; post_traversal_rec(root->left, arr, idx); post_traversal_rec(root->right, arr, idx); arr[(*idx)++] = root->val; }
// 非递归方法1:使用栈+上次访问标记
void post_traversal_nrec(TreeNode *root, float *arr, int size) {
if (!root) return; int top = -1, idx = 0;
TreeNode **stack = (TreeNode **)malloc(sizeof(TreeNode*) * size), *cur = root, *lastVisited = NULL; // lastVisited 用于记录上一个访问的节点
// 1. 压栈的同时,将当前指针移动到最左边的节点。2. 如果右子节点存在且未被访问过,则将指针移动到右子节点。3. 否则,出栈,获取节点值。4. 记录上一个访问的节点。循环1-4直到栈为空。
while (top >=0 || cur){
while(cur) {
stack[++top] = cur; cur = cur->left; } cur = stack[top];
if (cur->right && cur->right != lastVisited) {
cur = cur->right; }
else {
arr[idx++] = cur->val; lastVisited = cur; top--; cur = NULL; }
}
}
// 非递归方法2:使用双栈
void post_traversal_nrec2(TreeNode *root, float *arr, int size){
if (!root) return; int top1 = -1, top2 = -1, idx = 0;
// 栈1用于存储节点,栈2用于存储栈1出栈的节点。栈1出栈的顺序是根右左,栈2出栈的顺序是左右根。
TreeNode **stack1 = (TreeNode **)malloc(sizeof(TreeNode*) * size), **stack2 = (TreeNode **)malloc(sizeof(TreeNode*) * size); stack1[++top1] = root;
// 遍历栈1,将节点出栈,存入栈2, 入栈左右子节点。
while (top1 >= 0){
TreeNode *node = stack1[top1--]; stack2[++top2] = node; if (node->left) stack1[++top1] = node->left; if (node->right) stack1[++top1] = node->right; }
// 遍历栈2,将节点出栈,存入结果数组。
while (top2 >= 0) arr[idx++] = stack2[top2--]->val;
}
int main(){
// 初始化二叉树
float *x = (float *)malloc(N * sizeof(float)); TreeNode *root, node[N]; root = &node[0];
for (int i = 0; i < N; i++) {
node[i].val = i; node[i].left = NULL; node[i].right = NULL; }
node[0].left = &node[1]; node[0].right = &node[2]; node[1].left = &node[3]; node[1].right = &node[4];
node[2].left = &node[5]; node[2].right = &node[6]; node[3].left = &node[7]; node[3].right = &node[8]; node[4].left = &node[9];
TreeNode *tmp = (TreeNode* )malloc(sizeof(TreeNode)); node[0].left = tmp; tmp->left = &node[1]; node[0].left = &node[1]; // 模拟插入节点和删除节点
float *arr = (float *)malloc(sizeof(float) * N); int idx = 0; // 存放遍历结果
post_traversal_rec(root, arr, &idx); prtArr(arr, N); post_traversal_nrec2(root, arr, N); prtArr(arr, N); return 0; // 后序遍历
}