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

2019年7月18日06:46:57 发表评论 278 views

树在数据结构中是非常重要的一部分,树的应用有很多很多,树的种类也有很多很多,今天我们就先来创建一个普通的树。

首先,树的形状就是类似这个样子的:

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

它最顶上面的点叫做树的根节点,一棵树也只能有一个根节点,在节点下面可以有多个子节点,子节点的数量,我们这里不做要求,而没有子节点的节点叫做叶子节点。

好,关于树的基本概念就介绍到这里了,话多千遍不如动手做一遍,接下来我们边做边学,我们来创建一棵树:

# 定义一个普通的树类
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

这就是我们定义好的树类了,并给树添加了三个方法,分别是获取节点数据、设置节点数据、添加子节点、获取子节点。

这里的树类其实是一个节点类,很多个这样的节点可以构成一棵树,而我们就用根节点来代表这颗树。

接下来我们实例化一棵树:

# 初始化一个树
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代码实现树及深度、广度优先遍历(递归和非递归)

OK,我们的树已经实例化好了,我们先来对它分别采用递归和非递归的方式进行广度优先遍历:

广度优先遍历

广度优先遍历,就是从上往下,一层一层从左到右对树进行遍历。

在用非递归方式进行广度优先遍历的时候,我们需要用到前面介绍过的队列类型,所以我们来定义一个队列类:

# 用以实现广度优先遍历
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)

用队列实现广度优先遍历

利用队列我们只要在节点出队的时候让该节点的子节点入队即可。

# 广度优先遍历
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

调用一下:

print(breadthFirst(tree))

输出:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

递归实现广度优先遍历

# 递归方式实现广度优先遍历
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

调用一下:

print(breadthFirstByRecursion(tree))

输出:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

深度优先遍历

深度优先遍历,就是从上往下,从左到右,先遍历节点的子节点再遍历节点的兄弟节点。

采用非递归方式实现深度优先遍历呢,我们需要用到前面介绍过的堆栈结构,所以我们现在定义一个堆栈类吧:

# 用以实现深度优先遍历
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()

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

实现深度优先遍历,我们只要在节点出栈的时候把该节点的子节点从左到右压入堆栈即可。

# 深度优先遍历
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

调用一下:

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

输出:[0, 1, 4, 5, 2, 6, 7, 3, 8, 9]

递归实现深度优先遍历

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

调用一下:

print(depthFirstByRecursion(tree))

输出:[0, 1, 4, 5, 2, 6, 7, 3, 8, 9]

好啦,今天我们的树就介绍到这里了,对于广度优先遍历的递归实现,你有更好的方法吗?

发表评论

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