二叉树的前中后序递归和非递归遍历(c语言实现)

使用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; // 后序遍历
}

猜你喜欢

转载自blog.csdn.net/Cony_14/article/details/141784715