为防止广告,目前nocow只有登录用户能够创建新页面。如要创建页面请先登录/注册(新用户需要等待1个小时才能正常使用该功能)。

二叉树的遍历

来自NOCOW
跳转到: 导航, 搜索

这些内容太短,或是重要性比较差,不适合独立成一个条目。

请把这些内容移动到适当位置,或者在讨论页讨论

我们经常希望访问树中的每一个结点并且查看它的值。有很多常见的顺序来访问所有的结点,而且每一种都有有用的性质。

[编辑] 前(先)序、中序、后序遍历

遍历二叉树:L、D、R分别表示遍历左子树、访问根结点和遍历右子树,则先(根)序遍历二叉树的顺序是DLR,中(根)序遍历二叉树的顺序是LDR,后(根)序遍历二叉树的顺序是LRD。还有按层遍历二叉树。这些方法的时间复杂度都是O(n),n为结点个数。

如果T2是由有序树T转换而来的二叉树,那么T中结点的前序就是T2中结点的前序,T中结点的后序就是T2中结点的中序。任何一棵二叉树的叶结点在先序、中序和后序遍历中的相对次序不发改变。设n,m为一棵二叉树上的两个结点,在中序遍历时,n在m前的条件是n在m的左方。前序序列和中序序列相同的二叉树为空树或任一结点均无左孩子的非空二叉树;中序序列和后序序列相同的二叉树为空树或任一结点均无右孩子的非空二叉树;前序序列和后序序列相同的二叉树为空树或仅有一个结点的二叉树。

假设我们有一个包含值的value和指向两个子结点的leftright的树结点结构。我们可以写出这样的过程:

visit(node)
    print node.value
    if node.left  != null then visit(node.left)
    if node.right != null then visit(node.right)

这样会用中序打印出树中的值。在中序,每个结点在访问它的子结点之前访问。类似地,如果打印语句在最后,每个结点在访问他的子节点之后访问,树中的值会用后序来打印。在这两种情况中,左子树中的值比右子树中得值先打印。

visit(node)
    if node.left  != null then visit(node.left)
    print node.value
    if node.right != null then visit(node.right)

最后,上面的中序遍历,每个结点在访问左子树和右子树之间访问。这在遍历二叉搜索树时很常用,因为它能用递增的顺序来遍历所有的值。

为什么呢?如果n是二叉搜索树的结点,那么n的左子树的所有结点的值都比n的值要小,而且n的右子树的所有节点的值都比n的值要大。因此,如果我们顺序遍历左子树,然后访问n,然后顺序遍历右子树。我们就已经顺序访问了整个树。

一个简单的二叉树 在这个二叉树中,
  • 前序遍历的结果:2, 7, 2, 6, 5, 11, 5, 9, 4
  • 后序遍历的结果:2, 5, 11, 6, 7, 4, 9, 5, 2
  • 中序遍历的结果:2, 7, 5, 6, 11, 2, 5, 4, 9


以上的递归算法使用与树的高度成比例的栈空间。如果我们在每个结点中存储指向父结点的指针,那样可以使用迭代算法,只使用常数空间实现所有这些遍历。然而,指向父结点的指针占用更多的空间。这只在需要指向父节点的指针或栈空间有限时才使用。例如, 这是一个中序遍历的迭代算法:

visit(root)
    prev    := null
    current := root
    next    := null
    
    while current != null
        if prev == current.parent
            prev := current
            next := current.left
        if next == null or prev == current.left
            print current.value
            prev := current
            next := current.right
        if next == null or prev == current.right
            prev := current
            next := current.parent
        current := next
文件:Bitree.JPG 用二叉树表示下述表达式:a+b*(c-d)-e/f
  • 先序遍历的序列是:-+a*b-cd/ef
  • 中序遍历的序列是:a+b*c-d-e/f
  • 后序遍历的序列是:abcd-*+ef/-

[编辑] 深度优先遍历

在深度优先顺序中,我们希望从根结点访问最远的结点。和图的深度优先搜索不同的是,不需记住访问过的每一个结点,因为树中不会有环。前序,中序和后序遍历都是深度优先遍历的特例。参见深度优先搜索

[编辑] 广度优先遍历

和深度优先遍历不同,广度优先遍历会先访问离根节点最近的节点。参见广度优先搜索。 二叉树的广度优先遍历又称按层次遍历。算法借助队列实现。

个人工具