Java二叉树(三)--非递归的中序_先序_后序遍历二叉树

二叉树的递归遍历非常简单,但是非递归遍历就需要一点小技巧了,否则代码逻辑容易混乱,这里我给每一个节点定义里加入了一个访问标记flag,这样可以有效避免重复访问和代码逻辑不清楚的问题。

二叉树中序非递归遍历代码如下:

package binarytree;

import java.util.Stack;

/**
 * @author Gavenyeah
 * @date Time: 2016年5月13日上午8:46:38
 * @des: 
 */
//非递归的中序遍历二叉树

public class InOrder{
    public static void main(String args[]){
        Node head = new InOrder().getTree();
        new InOrder().inOrder(head);

    }
    public Node getTree(){
        Node head = new Node(1);
        Node node2 = new Node(2);
        Node node3 = new Node(3);
        Node node4 = new Node(4);
        Node node5 = new Node(5);
        Node node6 = new Node(6);
        Node node7 = new Node(7);
        Node node8 = new Node(8);

        head.left = node2;
        head.right = node3;
        node2.left = node4;
        node2.right = node5;
        node5.left = node7;
        node4.right= node6;
        node7.right= node8;

        return head;

    }
    public void inOrder(Node head){
        Stack<Node> stack  = new Stack<Node>();//用堆栈来实现非递归的中序遍历二叉树
        stack.push(head);
        Node cur = null;
        while(stack.size() > 0){
            head = stack. peek();
            while(head.left != null && head.left.flag == false){//有左子节点且未被访问过
                head = head.left;
                stack.push(head);
            }
            //出栈并访问节点
            cur = stack.pop();
            System.out.print(cur.data+" ");
            cur.flag = true;
            //进一步访问右子节点
            if(cur.right != null){
                stack.push(cur.right);
                head = cur.right;
            }
        }
    }
}

先序非递归遍历:

public void preOrder(Node head) {
        Stack<Node> stack = new Stack<Node>();
        stack.push(head);
        while (stack.size() > 0) {
            head = stack. peek();
            if (head.flag == false) {
                System.out.print(head.data + " ");
                head.flag = true;
            }

            while (head.left != null && head.left.flag == false) {
                head = head.left;
                System.out.print(head.data + " ");
                head.flag = true;
                stack.push(head);
            }
            head = stack.pop();// 没有左子树或左子树已被访问的节点可以直接出栈
            if (head.right != null && head.right.flag == false) {
                head = head.right;
                stack.push(head);
            } 
        }
    }

后序非递归遍历:

public void postOrder(Node head){
        Stack<Node> stack = new Stack<Node>();
        stack.push(head);
        while(stack.size() > 0){
            head = stack.peek();
            while(head.left != null && head.left.flag == false || 
                    head.right != null && head.right.flag == false){
                if(head.right != null && head.right.flag == false){
                    stack.push(head.right);
                }
                if(head.left != null && head.left.flag == false){
                    stack.push(head.left);
                }
                head = stack.peek();
            }
            head = stack.pop();
            System.out.print(head.data + " ");
            head.flag = true;
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然,二叉树遍历种主要方式:先序遍历(根-左-右)、中序遍历(左-根-右)和后序遍历(左-右-根)。非递归的层次遍历(也叫广度优先遍历,从上到下、从左到右)通常使用队列来辅助实现。 这里分别给出这些遍历非递归算法代码: 1. 层序遍历(广度优先遍历): ```c #include <stdio.h> #include <stdlib.h> #include <queue> struct TreeNode { int val; struct TreeNode *left; struct TreeNode *right; }; void levelOrder(struct TreeNode* root) { if (root == NULL) return; // 使用队列存储每一层的节点 queue<struct TreeNode*> q; q.push(root); while (!q.empty()) { int size = q.size(); for (int i = 0; i < size; i++) { struct TreeNode* node = q.front(); q.pop(); printf("%d ", node->val); // 打印当前节点值 if (node->left != NULL) q.push(node->left); if (node->right != NULL) q.push(node->right); } printf("\n"); // 换行表示新的一层 } } ``` 2. 先序遍历(递归和非递归两种方式,这里是非递归版本,使用栈): ```c void preorderNonRecursive(struct TreeNode* root) { if (root == NULL) return; stack<struct TreeNode*> s; s.push(root); while (!s.empty()) { struct TreeNode* node = s.top(); s.pop(); printf("%d ", node->val); // 打印当前节点值 if (node->right != NULL) s.push(node->right); if (node->left != NULL) s.push(node->left); } } ``` 3. 中序遍历非递归,同样使用栈): ```c void inorderNonRecursive(struct TreeNode* root) { if (root == NULL) return; stack<struct TreeNode*> s; struct TreeNode* curr = root; while (curr != NULL || !s.empty()) { while (curr != NULL) { s.push(curr); curr = curr->left; } curr = s.top(); s.pop(); printf("%d ", curr->val); // 打印当前节点值 curr = curr->right; } } ``` 4. 后序遍历非递归,使用两个栈): ```c void postorderNonRecursive(struct TreeNode* root) { if (root == NULL) return; stack<struct TreeNode*> s1, s2; s1.push(root); while (!s1.empty()) { struct TreeNode* node = s1.top(); s1.pop(); s2.push(node); if (node->left != NULL) s1.push(node->left); if (node->right != NULL) s1.push(node->right); } while (!s2.empty()) { struct TreeNode* node = s2.top(); s2.pop(); printf("%d ", node->val); // 打印当前节点值 } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值