python代码实现树及深度、广度优先遍历(递归和非递归)

2019-07-1806:46:57数据结构与算法Comments3,873 views字数 2769阅读模式

树在数据结构中是非常重要的一部分,树的应用有很多很多,树的种类也有很多很多,今天我们就先来创建一个普通的树。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/suanfa/14107.html

首先,树的形状就是类似这个样子的:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/suanfa/14107.html

python代码实现树及深度、广度优先遍历(递归和非递归)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/suanfa/14107.html

它最顶上面的点叫做树的根节点,一棵树也只能有一个根节点,在节点下面可以有多个子节点,子节点的数量,我们这里不做要求,而没有子节点的节点叫做叶子节点。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/suanfa/14107.html

好,关于树的基本概念就介绍到这里了,话多千遍不如动手做一遍,接下来我们边做边学,我们来创建一棵树:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/suanfa/14107.html

# 定义一个普通的树类
class Tree:
    def __init__(self, data):
        self.data = data
        self.children = []

    def get(self):
        return self.data
    
    def set(self):
        return self.data

    def addChild(self, child):
        self.children.append(child)

    def getChildren(self):
        return self.children

这就是我们定义好的树类了,并给树添加了三个方法,分别是获取节点数据、设置节点数据、添加子节点、获取子节点。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/suanfa/14107.html

这里的树类其实是一个节点类,很多个这样的节点可以构成一棵树,而我们就用根节点来代表这颗树。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/suanfa/14107.html

接下来我们实例化一棵树:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/suanfa/14107.html

# 初始化一个树
tree = Tree(0)
# 添加三个子节点
tree.addChild(Tree(1))
tree.addChild(Tree(2))
tree.addChild(Tree(3))
children = tree.getChildren()
# 每个子节点添加两个子节点
children[0].addChild(Tree(4))
children[0].addChild(Tree(5))
children[1].addChild(Tree(6))
children[1].addChild(Tree(7))
children[2].addChild(Tree(8))
children[2].addChild(Tree(9))

我们实例化好的树大概是这个样子的:
python代码实现树及深度、广度优先遍历(递归和非递归)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/suanfa/14107.html

OK,我们的树已经实例化好了,我们先来对它分别采用递归和非递归的方式进行广度优先遍历:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/suanfa/14107.html

广度优先遍历

广度优先遍历,就是从上往下,一层一层从左到右对树进行遍历。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/suanfa/14107.html

在用非递归方式进行广度优先遍历的时候,我们需要用到前面介绍过的队列类型,所以我们来定义一个队列类:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/suanfa/14107.html

# 用以实现广度优先遍历
class Queue():
    def __init__(self):
        self.__list = list()

    def isEmpty(self):
        return self.__list == []

    def push(self, data):
        self.__list.append(data)
    
    def pop(self):
        if self.isEmpty():
            return False
        return self.__list.pop(0)

用队列实现广度优先遍历

利用队列我们只要在节点出队的时候让该节点的子节点入队即可。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/suanfa/14107.html

# 广度优先遍历
def breadthFirst(tree):
    queue = Queue()
    queue.push(tree)
    result = []
    while not queue.isEmpty():
        node = queue.pop()
        result.append(node.data)
        for c in node.getChildren():
            queue.push(c)
    return result

调用一下:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/suanfa/14107.html

print(breadthFirst(tree))

输出:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]文章源自菜鸟学院-https://www.cainiaoxueyuan.com/suanfa/14107.html

递归实现广度优先遍历

# 递归方式实现广度优先遍历
def breadthFirstByRecursion(gen, index=0, nextGen=[], result=[]):
    
    if type(gen) == Tree:
        gen = [gen]
    result.append(gen[index].data)
    
    children = gen[index].getChildren()
    
    nextGen += children
    if index == len(gen)-1:
        if nextGen == []:
            return
        else:
            gen = nextGen
            nextGen = []
            index = 0
    else:
        index += 1
    breadthFirstByRecursion(gen, index, nextGen,result)

    return result

调用一下:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/suanfa/14107.html

print(breadthFirstByRecursion(tree))

输出:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]文章源自菜鸟学院-https://www.cainiaoxueyuan.com/suanfa/14107.html

深度优先遍历

深度优先遍历,就是从上往下,从左到右,先遍历节点的子节点再遍历节点的兄弟节点。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/suanfa/14107.html

采用非递归方式实现深度优先遍历呢,我们需要用到前面介绍过的堆栈结构,所以我们现在定义一个堆栈类吧:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/suanfa/14107.html

# 用以实现深度优先遍历
class Stack():
    def __init__(self):
        self.__list = list()

    def isEmpty(self):
        return self.__list == []

    def push(self, data):
        self.__list.append(data)
    
    def pop(self):
        if self.isEmpty():
            return False
        return self.__list.pop()

利用堆栈实现深度优先遍历

实现深度优先遍历,我们只要在节点出栈的时候把该节点的子节点从左到右压入堆栈即可。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/suanfa/14107.html

# 深度优先遍历
def depthFirst(tree):
    stack = Stack()
    stack.push(tree)
    result = []
    while not stack.isEmpty():
        node = stack.pop()
        result.append(node.data)
        children = node.getChildren()
        children = reversed(children)
        for c in children:
            stack.push(c)
    return result

调用一下:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/suanfa/14107.html

# 深度优先遍历
print(depthFirst(tree))

输出:[0, 1, 4, 5, 2, 6, 7, 3, 8, 9]文章源自菜鸟学院-https://www.cainiaoxueyuan.com/suanfa/14107.html

递归实现深度优先遍历

# 递归方式实现深度优先遍历
def depthFirstByRecursion(tree, result=[]):
    result.append(tree.data)
    children = tree.getChildren()
    for c in children:
        depthFirstByRecursion(c, result)
    return result

调用一下:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/suanfa/14107.html

print(depthFirstByRecursion(tree))

输出:[0, 1, 4, 5, 2, 6, 7, 3, 8, 9]文章源自菜鸟学院-https://www.cainiaoxueyuan.com/suanfa/14107.html

好啦,今天我们的树就介绍到这里了,对于广度优先遍历的递归实现,你有更好的方法吗?文章源自菜鸟学院-https://www.cainiaoxueyuan.com/suanfa/14107.html

  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/suanfa/14107.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定