资讯专栏INFORMATION COLUMN

前序遍历树

lylwyy2016 / 789人阅读

摘要:前序输出从这一路下来,有两个是正确的,如果先判断要遍历的节点是否已经遍历过的话,那么就走不通了,所以应该允许,点到就记一次输出,再来判断是否能继续往下走。

代码来自:pickle and cPickle – Python object serialization
首先树的结构,如图

import pickle

class Node(object):
    """A simple digraph where each node knows about the other nodes
    it leads to.
    """
    def __init__(self, name):
        self.name = name
        self.connections = []
        return

    def add_edge(self, node):
        "Create an edge between this node and the other."
        self.connections.append(node)
        return

    def __iter__(self):
        return iter(self.connections)

def preorder_traversal(root, seen=None, parent=None):
    """Generator function to yield the edges via a preorder traversal."""
    if seen is None:
        seen = set()
    yield (parent, root)
    if root in seen:
        return
    seen.add(root)
    for node in root:
        for (parent, subnode) in preorder_traversal(node, seen, root):
            yield (parent, subnode)
    return

def show_edges(root):
    "Print all of the edges in the graph."
    for parent, child in preorder_traversal(root):
        if not parent:
            continue
        print "%5s -> %2s (%s)" % (parent.name, child.name, id(child))

# Set up the nodes.
root = Node("root")
a = Node("a")
b = Node("b")
c = Node("c")

# Add edges between them.
root.add_edge(a)
root.add_edge(b)
a.add_edge(b)
b.add_edge(a)
b.add_edge(c)
a.add_edge(a)

print "ORIGINAL GRAPH:"
show_edges(root)

# Pickle and unpickle the graph to create
# a new set of nodes.
dumped = pickle.dumps(root)
reloaded = pickle.loads(dumped)

print
print "RELOADED GRAPH:"
show_edges(reloaded)

输出结果:

$ python pickle_cycle.py

ORIGINAL GRAPH:
 root ->  a (4299721744)
    a ->  b (4299721808)
    b ->  a (4299721744)
    b ->  c (4299721872)
    a ->  a (4299721744)
 root ->  b (4299721808)

RELOADED GRAPH:
 root ->  a (4299722000)
    a ->  b (4299722064)
    b ->  a (4299722000)
    b ->  c (4299722128)
    a ->  a (4299722000)
 root ->  b (4299722064)

其中preorder_traversal是生成器。这里记录下生成器方法的每一步的意思。

# root 要遍历的根节点
# seen 保存遍历过的节点(集合)
# parent 每次yield的父节点,有可能不存在
def preorder_traversal(root, seen=None, parent=None):
    """Generator function to yield the edges via a preorder traversal."""
    if seen is None: # 如果没有开始遍历,seen是空,初始化集合
        seen = set()
    yield (parent, root) # 记一次输出,这个要在下面判断之前
    if root in seen: # 要遍历的根节点是否已经遍历过,防止循环遍历
        return
    seen.add(root) # 保存已遍历的“根”节点
    for node in root: # 遍历子节点
        for (parent, subnode) in preorder_traversal(node, seen, root):
            yield (parent, subnode)
    return

一开始不明白的地方是这样

    yield (parent, root) # 记一次输出,这个要在下面判断之前
    if root in seen: # 要遍历的根节点是否已经遍历过,防止循环遍历
        return

为什么不是先判断呢。
看循环引用的情况。
前序输出从root -> a -> b -> a这一路下来,有两个a是正确的,
如果先判断要遍历的节点是否已经遍历过的话,那么
b -> a就走不通了,所以应该允许,点到就记一次输出,再来判断是否能继续往下走。
b -> a记一次输出,接下来发现a已经遍历过它的子节点了(a in seen),才停止不往下遍历。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/37585.html

相关文章

  • 二叉遍历

    摘要:前言本篇文章是在二叉排序树的基础上进行遍历查找与删除结点。接下来我们根据构造的这颗二叉树进行相应遍历查找与删除操作。遍历二叉树二叉树的遍历分为深度优先遍历和广度优先遍历。中序遍历二叉排序树,得到的数组是有序的且是升序的。 前言 本篇文章是在二叉排序树的基础上进行遍历、查找、与删除结点。 那么首先来看一下什么是二叉排序树? 二叉排序树 定义 二叉排序树,又称二叉查找树、二叉搜索树。 若...

    aboutU 评论0 收藏0
  • 【剑指offer】4.二叉遍历和重建

    摘要:第一行为前序遍历,第二行为中序遍历。例如输入前序遍历序列和中序遍历序列,则重建二叉树并返回。根据前序遍历和中序遍历的结果可以拿到左子中序遍历和右侧为右子树中序遍历左子树的前序遍历和右子树的前序遍历然后递归左子树和右子树的完成重建。 二叉树简介 基本结构: function TreeNode(x) { this.val = x; this.left = null; ...

    zhangyucha0 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<