二叉树的递归与非递归遍历

187 阅读2分钟

一,递归遍历

我们约定:

先序遍历顺序为根、左、右;

中序遍历顺序为左、根、右;

后序遍历顺序为左、右、根。

二叉树的结构为:

/**
 * lxw
 */
public class Node {
    public int value;
    public Node left;
    public Node right;
    public Node(int data) {
        this.value = data;
    }}

递归写法为:

/**
 * lxw recursion 
 * @param head
 */
public void recursion(Node head){
    if(null == head){
        return;
    } 
   //只在此处打印,为先序遍历
    System.out.println(head.value + "");
    recursion(head.left);
    //只在此处打印,为中序遍历
    System.out.println(head.value + "");
    recursion(head.right);
    //只在此处打印,为后序遍历
    System.out.println(head.value + "");}

二,非递归遍历

用递归方法解决的问题都能用非递归的方法实现。这是因为递归方法无非就是利用函数栈来保存信息,如果用自己申请的数据结构来代替函数栈,也可以实现相同的功能。

1,非递归先序遍历

  • 申请一个新的栈,记为stack。然后将头节点head压入stack中。

  • 从stack中弹出栈顶节点,记为cur,然后打印cur节点的值,再将节点cur的右孩子(不为空的话)先压入stack中,最后将cur的左孩子(不为空的话)压入stack中。

  • 不断重复第二步,直到stack为空。

    /**

    • lxw
    • @param head */ public void preUnRecursion(Node head) { if (null == head) { return; } Stack stack = new Stack(); stack.push(head); while (!stack.isEmpty()) { Node cur = stack.pop(); System.out.println(cur.value + ""); if (null != cur.right) { stack.push(cur.right); } if (null != cur.left) { stack.push(cur.left); } } }

2,非递归后序遍历

先序遍历的思路是:从栈中弹出节点的同时把该节点的右节点先压入栈里(如果有的话),再把该节点的左节点压入栈里(如果有的话),这样打印的结果是“根左右”。

延伸:如果想打印的结果是“根右左”,那么仿造先序遍历的思路(先压右后压左),去先压左后右即可。

延伸:如果想打印的结果是“左右根”,那么再上一个思路上把弹出的结果压到一个新的栈,压完新栈之后再把新栈的元素弹出,即为后序遍历。

/** 
* lxw 
* 
* @param head 
*/
public void posUnRecursion(Node head) {
    if (null == head) {
        return;
    }
    Stack<Node> stack = new Stack<Node>();
    Stack<Node> result = new Stack<Node>();
    stack.push(head);
    while (!stack.isEmpty()) {
        Node cur = stack.pop();
        result.push(cur);
        if (null != cur.left) {
            stack.push(cur.left);
        }
        if (null != cur.right) {
            stack.push(cur.right);
        }
    }
    while (!result.isEmpty()) {
        System.out.println(result.pop().value + "");
    }
}

3,非递归中序遍历

  • 申请一个新的栈,记为stack。初始时,令变量cur=head。

  • 先把cur节点压入栈中,对以cur节点为头的整棵子树来说,依次把左边界压入栈中,即不停地令cur=cur.left,然后重复步骤2.

  • 不断重复步骤2,直到发现cur为空,此时从stack中弹出一个节点,记为node,打印node的值,并让cur=node.right,然后继续重复步骤2.

  • 当stack为空且cur为空时,整个过程停止。

    /** 
    * lxw 
    * 
    * @param head 
    */
    public void inUnRecursion(Node head) {
        if (null == head) {
            return;
        }
        Stack<Node> stack = new Stack<Node>();
        stack.push(head);
        while (!stack.isEmpty() || null != head) {
            if (null != head) {
                stack.push(head);
                head = head.left;
            } else {
                Node node = stack.pop();
                System.out.println(node.value + "");
                head = node.right;
            }
        }
    }