前序遍历树
admin
2023-07-31 01:53:16
0

代码来自: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),才停止不往下遍历。

相关内容

热门资讯

Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
Apache Doris 2.... 亲爱的社区小伙伴们,我们很高兴地向大家宣布,Apache Doris 2.0.0 版本已于...
项目管理和工程管理的区别 项目管理 项目管理,顾名思义就是专注于开发和完成项目的管理,以实现目标并满足成功标准和项目要求。 工...