二叉树的前序,中序,后续,递归及非递归遍历的python实现

在计算机科学里,树的遍历(也称为树的搜索)是图的遍历的一种,指的是按照某种规则,不重复地访问某种树的所有节点的过程。具体的访问操作可能是检查节点的值、更新节点的值等。不同的遍历方式,其访问节点的顺序是不一样的。

遍历的种类

遍历方式的命名,源于其访问节点的顺序。最简单的划分:深度优先,广度优先。
深度优先遍历又可分为,前序遍历(pre-order), 中序遍历(in-order),后序遍历(post-order)
对于广度优先而言,遍历没有前序中序后序之分:给定一组已排序的子节点,其“广度优先”的遍历只有一种唯一的结果。
二叉树的递归算法相对简单,非递归算法实现要用到辅助栈,算法设计非常巧妙。
定义二叉树结构如下

class BinNode():
    def __init__(self, val):
        self.left = None
        self.right = None
        self.val = val

前序遍历(pre-order)

访问顺序:根左右

递归写法

def preOrder(sellf, root):
    if root == None:
        return
    print(root.val)
    self.preOrder(root.left)
    self.preOrder(root.right)

非递归写法
preOrder每次都将遇到的节点压入栈,当左子树遍历完毕后才从栈中弹出最后一个访问的节点,再访问其右子树。

def preOrder(self, root):
    if root == None:
        return
    stack = []
    node = root
    while node or stack:
        while node:
            # 从根节点开始,一直找它的左子树
            print(node.val)
            stack.append(node)
            node = node.left
        # while结束表示当前节点node为空,即前一个节点没有左子树了
        node = stack.pop()
        # 开始查看它的右子树
        node = node.right

中序遍历(In-order)

访问顺序:左根右

递归写法

def inOrder(self, root):
    if root == None:
        return
    self.inOrder(root.left)
    print(root.val)
    self.inOrder(root.right)

非递归写法
中序的非递归遍历与先序的非递归遍历类似。先序遍历是先访问节点,然后再将节点入栈,后中序遍历则是先入栈,然后节点弹出栈后再访问。

def inOrder(self,root):
    if root == None:
        return
    stack = []
    while node or stack:
        while node:
            # 从根节点开始,一直找到左子树
            stack.append(node)
            node = node.left
        # while结束表示当前节点node为空,即前一个节点没有左子树了
        node = stack.pop()
        print(node.val)
        node = node.right

后序遍历

访问顺序:左右根

递归写法

def postOrder(self,root):
    if root == None:
        return
    self.postOrder(root.left)
    self.postOrder(root.right)
    print(root.val)

非递归写法:
从直觉上来说,后序遍历对比中序遍历难度要增大很多。因为中序遍历节点序列有一点的连续性,而后续遍历则感觉有一定的跳跃性。先左,再右,最后才中间节点;访问左子树后,需要跳转到右子树,右子树访问完毕了再回溯至根节点并访问之,代码如下:

def postOrder(self,root):
    if root == None:
        return
    stack1 = []
    stack2 = []
    node = root
    stack1.append(node)
    while stack1:
    # 这个while循环用户找到后续遍历的逆序,存在stack2中
        node = stack1.pop()
        if node.left:
            stack1.append(node.left)
        if node.right:
            stack1.append(node.right)
        stack2.append(node)
    while stack2:
        print(stack2.pop().val)

广度优先遍历

广度优先搜索(Breadth First Search),又叫宽度优先搜索或横向优先搜索,是从根结点开始沿着树的宽度搜索遍历。
可以利用队列实现广度优先搜索。

广度优先遍历q与深度优先遍历的区别

广度优先遍历与深度优先遍历的区别在于:广度优先遍历是以层为顺序,将某一层上的所有节点都搜索到了之后才向下一层搜索;而深度优先遍历是将某一条枝桠上的所有节点都搜索到了之后,才转向搜索另一条枝桠上的所有节点。

from collections import deque
def BFS(self, root):
    if root == None:
        return
    quene = deque()
    node = root
    quene.append(node)
    while quene:
        node = quene.popleft()
        print(node.val)
        if node.left:
            quene.append(node.left)
        if node.right:
            quene.append(node.right)

你可能感兴趣的:(算法与数据结构)