c语言中如何实现树的遍历?

在 C 语言中实现树的遍历主要有以下几种方法:

前序遍历(递归)

  • 思路 :先访问根节点,再递归地前序遍历左子树,最后递归地前序遍历右子树。

  • 示例代码

    #include <stdio.h>
    
    // 定义树的节点结构
    typedef struct TreeNode {
        int val;
        struct TreeNode* left;
        struct TreeNode* right;
    } TreeNode;
    
    // 前序遍历函数
    void preorderTraversal(TreeNode* root) {
        if (root == NULL) {
            return;
        }
        // 访问根节点
        printf("%d ", root->val);
        // 递归遍历左子树
        preorderTraversal(root->left);
        // 递归遍历右子树
        preorderTraversal(root->right);
    }
    
    // 测试函数
    int main() {
        // 创建树的节点
        TreeNode root;
        root.val = 1;
        TreeNode leftChild;
        leftChild.val = 2;
        TreeNode rightChild;
        rightChild.val = 3;
        TreeNode leftLeftGrandchild;
        leftLeftGrandchild.val = 4;
        TreeNode leftRightGrandchild;
        leftRightGrandchild.val = 5;
    
        // 构建树的结构
        root.left = &leftChild;
        root.right = &rightChild;
        leftChild.left = &leftLeftGrandchild;
        leftChild.right = &leftRightGrandchild;
        rightChild.left = NULL;
        rightChild.right = NULL;
    
        // 进行前序遍历
        printf("前序遍历结果:");
        preorderTraversal(&root);
        printf("\n");
    
        return 0;
    }

中序遍历(递归)

  • 思路 :先递归地中序遍历左子树,再访问根节点,最后递归地中序遍历右子树。

  • 示例代码

    #include <stdio.h>
    
    // 定义树的节点结构
    typedef struct TreeNode {
        int val;
        struct TreeNode* left;
        struct TreeNode* right;
    } TreeNode;
    
    // 中序遍历函数
    void inorderTraversal(TreeNode* root) {
        if (root == NULL) {
            return;
        }
        // 递归遍历左子树
        inorderTraversal(root->left);
        // 访问根节点
        printf("%d ", root->val);
        // 递归遍历右子树
        inorderTraversal(root->right);
    }
    
    // 测试函数
    int main() {
        // 创建树的节点和构建树的结构(与前序遍历示例相同)
        TreeNode root;
        root.val = 1;
        TreeNode leftChild;
        leftChild.val = 2;
        TreeNode rightChild;
        rightChild.val = 3;
        TreeNode leftLeftGrandchild;
        leftLeftGrandchild.val = 4;
        TreeNode leftRightGrandchild;
        leftRightGrandchild.val = 5;
    
        root.left = &leftChild;
        root.right = &rightChild;
        leftChild.left = &leftLeftGrandchild;
        leftChild.right = &leftRightGrandchild;
        rightChild.left = NULL;
        rightChild.right = NULL;
    
        // 进行中序遍历
        printf("中序遍历结果:");
        inorderTraversal(&root);
        printf("\n");
    
        return 0;
    }

后序遍历(递归)

  • 思路 :先递归地后序遍历左子树,再递归地后序遍历右子树,最后访问根节点。

  • 示例代码

    #include <stdio.h>
    
    // 定义树的节点结构
    typedef struct TreeNode {
        int val;
        struct TreeNode* left;
        struct TreeNode* right;
    } TreeNode;
    
    // 后序遍历函数
    void postorderTraversal(TreeNode* root) {
        if (root == NULL) {
            return;
        }
        // 递归遍历左子树
        postorderTraversal(root->left);
        // 递归遍历右子树
        postorderTraversal(root->right);
        // 访问根节点
        printf("%d ", root->val);
    }
    
    // 测试函数
    int main() {
        // 创建树的节点和构建树的结构(与前序遍历示例相同)
        TreeNode root;
        root.val = 1;
        TreeNode leftChild;
        leftChild.val = 2;
        TreeNode rightChild;
        rightChild.val = 3;
        TreeNode leftLeftGrandchild;
        leftLeftGrandchild.val = 4;
        TreeNode leftRightGrandchild;
        leftRightGrandchild.val = 5;
    
        root.left = &leftChild;
        root.right = &rightChild;
        leftChild.left = &leftLeftGrandchild;
        leftChild.right = &leftRightGrandchild;
        rightChild.left = NULL;
        rightChild.right = NULL;
    
        // 进行后序遍历
        printf("后序遍历结果:");
        postorderTraversal(&root);
        printf("\n");
    
        return 0;
    }

    前序遍历(非递归)

  • 思路 :使用栈来辅助遍历。先将根节点压入栈中,然后循环执行以下操作:弹出栈顶节点并访问,若该节点有右孩子则将右孩子压入栈,若该节点有左孩子则将左孩子压入栈。

  • 示例代码

    #include <stdio.h>
    #include <stdlib.h>
    
    // 定义树的节点结构
    typedef struct TreeNode {
        int val;
        struct TreeNode* left;
        struct TreeNode* right;
    } TreeNode;
    
    // 定义栈的节点结构
    typedef struct StackNode {
        TreeNode* treeNode;
        struct StackNode* next;
    } StackNode;
    
    // 定义栈结构
    typedef struct Stack {
        StackNode* top;
    } Stack;
    
    // 初始化栈
    void initStack(Stack* stack) {
        stack->top = NULL;
    }
    
    // 判断栈是否为空
    int isEmpty(Stack* stack) {
        return stack->top == NULL;
    }
    
    // 入栈操作
    void push(Stack* stack, TreeNode* treeNode) {
        StackNode* newNode = (StackNode*)malloc(sizeof(StackNode));
        newNode->treeNode = treeNode;
        newNode->next = stack->top;
        stack->top = newNode;
    }
    
    // 出栈操作
    TreeNode* pop(Stack* stack) {
        if (isEmpty(stack)) {
            return NULL;
        }
        StackNode* temp = stack->top;
        TreeNode* treeNode = temp->treeNode;
        stack->top = temp->next;
        free(temp);
        return treeNode;
    }
    
    // 前序遍历函数(非递归)
    void preorderTraversalNonRecursive(TreeNode* root) {
        if (root == NULL) {
            return;
        }
        Stack stack;
        initStack(&stack);
        push(&stack, root);
        while (!isEmpty(&stack)) {
            TreeNode* node = pop(&stack);
            printf("%d ", node->val);
            // 先右后左压栈,保证出栈顺序是左右
            if (node->right) {
                push(&stack, node->right);
            }
            if (node->left) {
                push(&stack, node->left);
            }
        }
    }
    
    // 测试函数
    int main() {
        // 创建树的节点和构建树的结构(与前序遍历示例相同)
        TreeNode root;
        root.val = 1;
        TreeNode leftChild;
        leftChild.val = 2;
        TreeNode rightChild;
        rightChild.val = 3;
        TreeNode leftLeftGrandchild;
        leftLeftGrandchild.val = 4;
        TreeNode leftRightGrandchild;
        leftRightGrandchild.val = 5;
    
        root.left = &leftChild;
        root.right = &rightChild;
        leftChild.left = &leftLeftGrandchild;
        leftChild.right = &leftRightGrandchild;
        rightChild.left = NULL;
        rightChild.right = NULL;
    
        // 进行前序遍历(非递归)
        printf("前序遍历(非递归)结果:");
        preorderTraversalNonRecursive(&root);
        printf("\n");
    
        return 0;
    }

    中序遍历(非递归)

  • 思路 :同样使用栈来辅助遍历。初始化时将根节点压入栈中,然后循环执行以下操作:一直向左子树移动并压栈,直到左子树为空,然后弹出栈顶节点并访问,接着将当前节点指向该节点的右孩子,重复上述过程。

  • 示例代码

    #include <stdio.h>
    #include <stdlib.h>
    
    // 定义树的节点结构
    typedef struct TreeNode {
        int val;
        struct TreeNode* left;
        struct TreeNode* right;
    } TreeNode;
    
    // 定义栈的节点结构和栈结构(与前序遍历非递归示例相同)
    typedef struct StackNode {
        TreeNode* treeNode;
        struct StackNode* next;
    } StackNode;
    
    typedef struct Stack {
        StackNode* top;
    } Stack;
    
    void initStack(Stack* stack) {
        stack->top = NULL;
    }
    
    int isEmpty(Stack* stack) {
        return stack->top == NULL;
    }
    
    void push(Stack* stack, TreeNode* treeNode) {
        StackNode* newNode = (StackNode*)malloc(sizeof(StackNode));
        newNode->treeNode = treeNode;
        newNode->next = stack->top;
        stack->top = newNode;
    }
    
    TreeNode* pop(Stack* stack) {
        if (isEmpty(stack)) {
            return NULL;
        }
        StackNode* temp = stack->top;
        TreeNode* treeNode = temp->treeNode;
        stack->top = temp->next;
        free(temp);
        return treeNode;
    }
    
    // 中序遍历函数(非递归)
    void inorderTraversalNonRecursive(TreeNode* root) {
        if (root == NULL) {
            return;
        }
        Stack stack;
        initStack(&stack);
        TreeNode* current = root;
        while (current != NULL || !isEmpty(&stack)) {
            // 一直向左子树移动并压栈
            while (current != NULL) {
                push(&stack, current);
                current = current->left;
            }
            // 弹出栈顶节点并访问
            current = pop(&stack);
            printf("%d ", current->val);
            // 转向右子树
            current = current->right;
        }
    }
    
    // 测试函数
    int main() {
        // 创建树的节点和构建树的结构(与前序遍历示例相同)
        TreeNode root;
        root.val = 1;
        TreeNode leftChild;
        leftChild.val = 2;
        TreeNode rightChild;
        rightChild.val = 3;
        TreeNode leftLeftGrandchild;
        leftLeftGrandchild.val = 4;
        TreeNode leftRightGrandchild;
        leftRightGrandchild.val = 5;
    
        root.left = &leftChild;
        root.right = &rightChild;
        leftChild.left = &leftLeftGrandchild;
        leftChild.right = &leftRightGrandchild;
        rightChild.left = NULL;
        rightChild.right = NULL;
    
        // 进行中序遍历(非递归)
        printf("中序遍历(非递归)结果:");
        inorderTraversalNonRecursive(&root);
        printf("\n");
    
        return 0;
    }

    后序遍历(非递归)

  • 思路 :使用两个栈来辅助遍历。先将根节点压入第一个栈中,然后循环执行以下操作:弹出栈顶节点并压入第二个栈,若该节点有左孩子则将左孩子压入第一个栈,若该节点有右孩子则将右孩子压入第一个栈。最后,依次弹出第二个栈中的节点并访问。

  • 示例代码

    #include <stdio.h>
    #include <stdlib.h>
    
    // 定义树的节点结构
    typedef struct TreeNode {
        int val;
        struct TreeNode* left;
        struct TreeNode* right;
    } TreeNode;
    
    // 定义栈的节点结构和栈结构(与前序遍历非递归示例相同)
    typedef struct StackNode {
        TreeNode* treeNode;
        struct StackNode* next;
    } StackNode;
    
    typedef struct Stack {
        StackNode* top;
    } Stack;
    
    void initStack(Stack* stack) {
        stack->top = NULL;
    }
    
    int isEmpty(Stack* stack) {
        return stack->top == NULL;
    }
    
    void push(Stack* stack, TreeNode* treeNode) {
        StackNode* newNode = (StackNode*)malloc(sizeof(StackNode));
        newNode->treeNode = treeNode;
        newNode->next = stack->top;
        stack->top = newNode;
    }
    
    TreeNode* pop(Stack* stack) {
        if (isEmpty(stack)) {
            return NULL;
        }
        StackNode* temp = stack->top;
        TreeNode* treeNode = temp->treeNode;
        stack->top = temp->next;
        free(temp);
        return treeNode;
    }
    
    // 后序遍历函数(非递归)
    void postorderTraversalNonRecursive(TreeNode* root) {
        if (root == NULL) {
            return;
        }
        Stack stack1, stack2;
        initStack(&stack1);
        initStack(&stack2);
        push(&stack1, root);
        while (!isEmpty(&stack1)) {
            TreeNode* node = pop(&stack1);
            push(&stack2, node);
            // 先左后右压栈,保证出栈顺序是左右
            if (node->left) {
                push(&stack1, node->left);
            }
            if (node->right) {
                push(&stack1, node->right);
            }
        }
        // 弹出 stack2 中的节点并访问
        while (!isEmpty(&stack2)) {
            TreeNode* node = pop(&stack2);
            printf("%d ", node->val);
        }
    }
    
    // 测试函数
    int main() {
        // 创建树的节点和构建树的结构(与前序遍历示例相同)
        TreeNode root;
        root.val = 1;
        TreeNode leftChild;
        leftChild.val = 2;
        TreeNode rightChild;
        rightChild.val = 3;
        TreeNode leftLeftGrandchild;
        leftLeftGrandchild.val = 4;
        TreeNode leftRightGrandchild;
        leftRightGrandchild.val = 5;
    
        root.left = &leftChild;
        root.right = &rightChild;
        leftChild.left = &leftLeftGrandchild;
        leftChild.right = &leftRightGrandchild;
        rightChild.left = NULL;
        rightChild.right = NULL;
    
        // 进行后序遍历(非递归)
        printf("后序遍历(非递归)结果:");
        postorderTraversalNonRecursive(&root);
        printf("\n");
    
        return 0;
    }

    以上是 C 语言中实现树的遍历的常见方法,你可以根据实际需求选择合适的遍历方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

搬砖牛马人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值