二叉树前中后序遍历的递归及非递归实现(附代码)

完整代码见git仓库:https://github.com/wangshen2016/Algorithm
树结构如下:

static class Node{
        public int value;
        public Node lchild = null;
        public Node rchild = null;

        public Node(int value) {
            this.value = value;
        }

        public Node(int value, Node lchild, Node rchild) {
            this.value = value;
            this.lchild = lchild;
            this.rchild = rchild;
        }
    }

1. 先序遍历

出栈顺序:头左右

  1. 准备一个栈
  2. 先压头节点
  3. 弹栈打印
  4. 如果有右孩子,压入右孩子
  5. 如果有左孩子,压入左孩子

递归

public static void pre(Node head) {
        if (head == null) {
            return;
        }
        System.out.print(head.value + " ");
        pre(head.lchild);
        pre(head.rchild);
    }

非递归

public static void pre2(Node head) {
        if (head == null) {
            return;
        }
        Deque<Node> stack = new ArrayDeque<>();
        stack.push(head);
        while (!stack.isEmpty()) {
            Node pop = stack.pop();
            System.out.print(pop.value + " ");
            if (pop.rchild != null) {
                stack.push(pop.rchild);
            }
            if (pop.lchild != null) {
                stack.push(pop.lchild);
            }
        }
    }

2. 后序遍历

方案一:使用两个栈

出栈顺序:头右左,然后倒过来就是后序遍历

  1. 准备一个栈
  2. 先压头节点
  3. 弹栈并压入另一个栈
  4. 如果有左孩子,压入左孩子
  5. 如果有右孩子,压入右孩子
  6. 最后依次弹出第二个栈并打印
方案二:使用一个栈

使用两个指针h,c。h记录上一次打印的节点,c记录栈顶元素

  1. 头节点入栈
  2. c记录栈顶元素
  3. if:如果c有左孩子且上一次打印的节点不是c的左右孩子,那么c的左孩子入栈,继续2;
    else if:如果c有右孩子,且上一次打印的不是c的右孩子,那么c的右孩子入栈,继续2;
    else:弹出栈顶元素并打印,h记录打印的元素

递归

public static void post(Node head) {
        if (head == null) {
            return;
        }
        post(head.lchild);
        post(head.rchild);
        System.out.print(head.value + " ");
    }

非递归方案一

public static void post2(Node head) {
        if (head == null) {
            return;
        }
        Deque<Node> stack = new ArrayDeque<>();
        Deque<Node> stack2 = new ArrayDeque<>();
        stack.push(head);
        while (!stack.isEmpty()) {
            Node pop = stack.pop();
            stack2.push(pop);
            if (pop.lchild != null) {
                stack.push(pop.lchild);
            }
            if (pop.rchild != null) {
                stack.push(pop.rchild);
            }
        }
        while (!stack2.isEmpty()) {
            System.out.print(stack2.pop().value + " ");
        }
    }

非递归方案2

public static void post3(Node h) {
        if (h == null) {
            return;
        }
        Deque<Node> stack = new ArrayDeque<>();
        Node c = null;
        stack.push(h);
        while (!stack.isEmpty()) {
            c = stack.peek();
            if (c.lchild != null && h != c.lchild && h != c.rchild) {
                stack.push(c.lchild);
            } else if (c.rchild != null && h != c.rchild) {
                stack.push(c.rchild);
            } else {
                Node pop = stack.pop();
                System.out.print(pop.value + " ");
                h = pop;
            }
        }
    }

3. 中序遍历

  1. 准备一个栈
  2. 将整条左子树依次入栈
  3. 如果左孩子为空,弹栈打印,并将当前节点指向其右孩子,继续到第2步执行

递归

public static void in(Node head) {
        if (head == null) {
            return;
        }
        in(head.lchild);
        System.out.print(head.value + " ");
        in(head.rchild);
    }

非递归

public static void in2(Node head) {
        if (head != null) {
            Deque<Node> stack = new ArrayDeque<>();
            while (!stack.isEmpty() || head != null) {
                if (head != null) {
                    stack.push(head);
                    head = head.lchild;
                } else {
                    head = stack.pop();
                    System.out.print(head.value + " ");
                    head = head.rchild;
                }
            }
        }
    }

4. 测试代码

public static void main(String[] args) {
        Node n1 = new Node(8);
        Node n2 = new Node(5);
        Node n3 = new Node(4);
        Node n4 = new Node(2);
        Node n5 = new Node(3);
        Node n6 = new Node(1);
        Node n7 = new Node(6);
        Node n8 = new Node(9);
        Node n9 = new Node(7);
        Node n10 = new Node(0);
        n1.lchild = n2;
        n1.rchild = n3;
        n2.lchild = n4;
        n2.rchild = n5;
        n3.rchild = n7;
        n5.lchild = n6;
        n7.lchild = n8;
        n8.lchild = n9;
        n8.rchild = n10;

        pre(n1);
        System.out.println();
        pre2(n1);
        System.out.println();
        in(n1);
        System.out.println();
        in2(n1);
        System.out.println();
        post(n1);
        System.out.println();
        post2(n1);
        System.out.println();
        post3(n1);
    }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是C语言实现二叉树前中后序遍历非递归完整代码: ```c #include <stdio.h> #include <stdlib.h> #define MAXSIZE 100 typedef struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; } TreeNode; typedef struct Stack { TreeNode *data[MAXSIZE]; int top; } Stack; void initStack(Stack *s) { s->top = -1; } int isEmpty(Stack *s) { return s->top == -1; } int isFull(Stack *s) { return s->top == MAXSIZE - 1; } void push(Stack *s, TreeNode *node) { if (isFull(s)) { printf("Stack is full.\n"); return; } s->data[++s->top] = node; } TreeNode *pop(Stack *s) { if (isEmpty(s)) { printf("Stack is empty.\n"); return NULL; } return s->data[s->top--]; } TreeNode *createTree() { int val; scanf("%d", &val); if (val == -1) { return NULL; } TreeNode *root = (TreeNode *)malloc(sizeof(TreeNode)); root->val = val; root->left = createTree(); root->right = createTree(); return root; } void preOrder(TreeNode *root) { if (root == NULL) { return; } Stack s; initStack(&s); push(&s, root); while (!isEmpty(&s)) { TreeNode *node = pop(&s); printf("%d ", node->val); if (node->right != NULL) { push(&s, node->right); } if (node->left != NULL) { push(&s, node->left); } } } void inOrder(TreeNode *root) { if (root == NULL) { return; } Stack s; initStack(&s); TreeNode *node = root; while (node != NULL || !isEmpty(&s)) { while (node != NULL) { push(&s, node); node = node->left; } node = pop(&s); printf("%d ", node->val); node = node->right; } } void postOrder(TreeNode *root) { if (root == NULL) { return; } Stack s1, s2; initStack(&s1); initStack(&s2); push(&s1, root); while (!isEmpty(&s1)) { TreeNode *node = pop(&s1); push(&s2, node); if (node->left != NULL) { push(&s1, node->left); } if (node->right != NULL) { push(&s1, node->right); } } while (!isEmpty(&s2)) { TreeNode *node = pop(&s2); printf("%d ", node->val); } } int main() { TreeNode *root = createTree(); printf("Preorder traversal: "); preOrder(root); printf("\nInorder traversal: "); inOrder(root); printf("\nPostorder traversal: "); postOrder(root); return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值