• 数据结构-树以及深度、广度优先遍历(递归和非递归,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))
    

    我们实例化好的树大概是这个样子的:
    树

    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]

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

  • 相关阅读:
    HDU-6801 2020HDU多校第三场T11 (生成函数)
    [HDU-6791] 2020HDU多校第三场T1(回文自动机)
    回文自动机 (PAM,Palindrome Automaton)
    字符串的Period(周期),Border
    「APIO2019」路灯 (K-D Tree / 树套树 / CDQ + 树状数组)
    「APIO2019」桥梁(询问分块+并查集)
    「APIO2019」奇怪装置
    「APIO2018」选圆圈(K-D Tree/CDQ+Set)
    堆小结
    【[HNOI/AHOI2018]毒瘤】
  • 原文地址:https://www.cnblogs.com/dongyangblog/p/11204612.html
Copyright © 2020-2023  润新知