非递归方式遍历二叉树

非递归方式遍历二叉树

二叉树的遍历按照访问根节点与子节点的顺序分为先序(根,左,右)、中序(左、根、右)、后序(左、右、根)三种。通常会使用递归的方式进行遍历,实现起来非常简单。

假设结点的定义如下:

class Node:
    value = None
    left = None
    right = None

先序遍历的一般实现如下:

def preorder_traverse(node):
    if node is None:
        return
    do_something(node)
    preorder_traverse(node.left)
    preorder_traverse(node.right)

中序遍历的一般实现如下:

def inorder_traverse(node):
    if node is None:
        return
    inorder_traverse(node.left)
    do_something(node)
    inorder_tranverse(node.right)

后序遍历的一般实现如下:

def postorder_traverse(node):
    if node is None:
        return
    postorder_traverse(node.left)
    postorder_traverse(node.right)
    do_something(node)

递归方式直观易懂容易实现。在限定不使用递归的方式,通过一个辅助的栈,也能实现以上 3 种遍历。在处理时需要注意,栈是固定的后进先出的数据结构,要注意数据顺序。原来都是先访问左结点后右结点,那么在压栈时就要先右结点后左结点。

先序遍历的非递归实现如下:

def preorder_traverse(node):
    stack = Stack()
    if node:
        stack.push(node)
    while stack.length() > 0:
        cur = stack.pop()
        do_something(cur)
        if cur.right:
            stack.push(cur.right)
        if cur.left:
            stack.push(cur.left)

中序和后序遍历,需要辅助的数据来确定结点是否已经访问过(通过调整树结构也可以达到相同目的,但不太优雅),节点定义调整为:

class Node:
    value = None
    left = None
    right = None
    visited = False

那么中序遍历为:

def inorder_traverse(node):
    stack = Stack()
    if node:
        stack.push(node)
    while stack.length() > 0:
        cur = stack.pop()
        if cur.visited:
            do_something(cur)
        else:
            if cur.right:
                stack.push(cur.right)
            stack.push(cur)
            if cur.left:
                stack.append(cur.left)
            cur.visited = True

后序遍历为:

def postorder_traverse(node):
    stack = Stack()
    if node:
        stack.push(node)
    while stack.length() > 0:
        cur = stack.pop()
        if cur.visited:
            do_something(cur)
        else:
            stack.push(cur)
            if cur.right:
                stack.push(cur.right)
            if cur.left:
                stack.push(cur.left)
            cur.visited = True

中序和后序遍历中,把同一个父结点做了两次压栈操作,这里还有优化的空间,通过判断减少压栈操作。先序遍历也可写成与中序和后序相同结构的方式,使用 visited 变量记录结点是否已访问,然后用相同的压栈方式处理。

posted @ 2016-08-01 10:28  drop *  阅读(278)  评论(0编辑  收藏  举报