...

『二叉树』详解「广度遍历・深度遍历」的Python实现

1. 整体概念

本来只是想写个堆排序的,谁知道因为种种原因有很多不懂的,越写越长。
所以就在这里整理出来,分为二叉树和堆,2篇文章。
先把结构理顺一下。
想知道什么是堆排序就要按照这个顺序依次向下了解有个全局意识。

树→二叉树→完全二叉树→堆→堆化→堆排序

2. 关于树

2-1 什么是树

树(英语:tree)是一种抽象数据类型(ADT)或是实作这种抽象数据类型的数据结构,用来模拟具有树状结构性质的数据集合。
树,是节点(node)的集合(A tree is a collection of nodes)。
它是由n(n>=1)个有限节点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点:

  • 每个节点有零个或多个子节点;
  • 没有父节点的节点称为根节点;
  • 每一个非根节点有且只有一个父节点;
  • 除了根节点外,每个子节点可以分为多个不相交的子树;

简言之,就是现实生活中的树倒过来而已!

2-1-1 树的几个重要概念

  • 根节点root 。不用说了,一个数只有一个跟,操作系统只有1个根目录,唯一性!
  • 子节点child・父节点parent。 有爸爸的节点就是子节点,有儿子的节点就是父节点。
  • 树叶leaves 。最后一层,没有任何子节点的就是树叶。
  • 深度(高度)。就是层次。金字塔一样,看到顶尖有几层就多少度
    ※有一种说法是分开高度很深度,深度相对于节点而言,高度针对于整个树而言。
              18             # Root 根节点                ---第一层  
           /       \    
         15         30        # parent/child 父节点/子节点  ---第二层  
        /  \        /  \  
      40    50    100  40    # leaves 叶子                ---第三层  

2-1-2 树的应用场景

1.xml,html等,那么编写这些东西的解析器的时候,不可避免用到树
2.路由协议就是使用了树的算法
3.mysql数据库索引
4.文件系统的目录结构
5.所以很多经典的AI算法其实都是树搜索,此外机器学习中的decision tree也是树结构

※ 给个小建议,学习数据结构或者计算机一定要学好专用名词的英语。原因不外乎有这几个,1就是有些名词翻译过来会有多个版本,容易引起混淆,但是英文只有一个。2 在遇到中文资源无法解决的问题时,可以通过专用名词来查找外网。(这真的跟你英文能力无关,就是个单词而已)

2-2 树的分类

树有很多种类,下面有个图,但我们重点讨论的是其中的1个种类。二叉树。
此处应该有个图

目前还没。。。

2-2 什么是二叉树 Binary Tree

二叉树是每个节点最多有两个子树的树结构。通常子树被称作「左子树」(left subtree)和「右子树」(right subtree)。就是只能有2个分叉!

2-2-1 二叉树特性

a. 第i层的结点最多2i>
b. 高度为k的二叉树最多有2(k+1)-1个结点 (空树的高度为-1
c. 对于任意一颗二叉树。其叶子结点树定为m,所有度为2的结点定位n 那么 m-n = 1

2-3 什么是完全二叉树 Complete Binary Tree

这个就是二叉树的进一步分类得来的,其实就是按照从上到下从左到右的顺序进行排列的二叉树。

以下都是二叉树。

              18      
           /       \    
         15         30    
        /  \        /  \  
      40    50    100   40  


               18  
           /       \    
         15         30    
        /  \        /  \  
      40    50    100   40  
     /  \   /  
    8   7  9   

其中容易跟完全二叉树混淆的有几个概念。

参考链接:什么是二叉树

  • Full Binary Tree 满二叉树
  • Perfect Binary Tree 完美二叉树
  • Balanced Binary Tree 平衡二叉树

3.代码实现二叉树遍历

3-1 二叉树&添加节点

# 节点类  
class Node(object):  

    def __init__(self, elem):  
    # 初始化 root节点,左子节点,右子节点  
        self.elem = elem  
        self.lchild = None  
        self.rchild = None  

# 树类  
class Tree(object):  
 # 初始化一个空节点  
    def __init__(self):  
        self.root = None  

    # 增加节点  
    def add(self, elem):  
        node = Node(elem)  
        if self.root is None:  
            self.root = node  
            return  
        # 这里很重要的地方在于用一个队列来存放节点  
        queue = [self.root]  
        # 只要队列不为空就继续遍历  
        while queue:  
            # pop出来最后的节点  
            current_node = queue.pop(0)  
            if current_node.lchild is None:  
                current_node.lchild = node  
                return  
            else:  
                queue.append(current_node.lchild)  
            if current_node.rchild is None:  
                current_node.rchild = node  
                return  
            else:  
                queue.append(current_node.rchild)  

3-2 广度遍历

DFS => Depth First Search 深度优先
BFS => Breadth First Search 广度优先

# 广度遍历            
def breath_travle(self):  
  if self.root is None:  
    return  
  queue = [self.root]  
  # 只要队列不为空就继续遍历  
  while queue:  
    current_node = queue.pop(0)  
    print(current_node.elem, end=' ')  
    if current_node.lchild is not None:  
      queue.append(current_node.lchild)  
      if current_node.rchild is not None:  
        queue.append(current_node.rchild)  

3-3 深度遍历(先序・中序・后序)

# 深度遍历(先序)  
def preorder(self, node):  
    if node is None:  
        return  
    print(node.elem, end=' ')  
    self.preorder(node.lchild)  
    self.preorder(node.rchild)  

# 深度遍历(中序)  
def inorder(self, node):  
    if node is None:  
        return  
    self.inorder(node.lchild)  
    print(node.elem, end=' ')         
    self.inorder(node.rchild)     

# 深度遍历(后序)  
def postorder(self, node):  
    if node is None:  
        return        
    self.postorder(node.lchild)  
    self.postorder(node.rchild)  
    print(node.elem, end=' ')  

3-4 验证合体

# 节点类  
class Node(object):  
    def __init__(self, elem):  
        self.elem = elem  
        self.lchild = None  
        self.rchild = None  
# 树类  
class Tree(object):  
    def __init__(self):  
        self.root = None  
    # 增加节点  
    def add(self, elem):  
        node = Node(elem)  
        if self.root is None:  
            self.root = node  
            return  
        # 这里很重要的地方在于用一个队列来存放节点  
        queue = [self.root]  
        # 只要队列不为空就继续遍历  
        while queue:  
            # pop出来最后的节点  
            current_node = queue.pop(0)  
            if current_node.lchild is None:  
                current_node.lchild = node  
                return  
            else:  
                queue.append(current_node.lchild)  
            if current_node.rchild is None:  
                current_node.rchild = node  
                return  
            else:  
                queue.append(current_node.rchild)  
    # 广度遍历            
    def breath_travle(self):  
        if self.root is None:  
            return  
        queue = [self.root]  
        # 只要队列不为空就继续遍历  
        while queue:  
            current_node = queue.pop(0)  
            print(current_node.elem, end=' ')  
            if current_node.lchild is not None:  
                queue.append(current_node.lchild)  
            if current_node.rchild is not None:  
                queue.append(current_node.rchild)  

    # 深度遍历(先序)  
    def preorder(self, node):  
        if node is None:  
            return  
        print(node.elem, end=' ')  
        self.preorder(node.lchild)  
        self.preorder(node.rchild)  

    # 深度遍历(中序)  
    def inorder(self, node):  
        if node is None:  
            return  
        self.inorder(node.lchild)  
        print(node.elem, end=' ')         
        self.inorder(node.rchild)     

    # 深度遍历(后序)  
    def postorder(self, node):  
        if node is None:  
            return        
        self.postorder(node.lchild)  
        self.postorder(node.rchild)  
        print(node.elem, end=' ')  


if __name__ == "__main__":  
    tree = Tree()  
    tree.add(0)  
    tree.add(1)  
    tree.add(2)  
    tree.add(3)  
    tree.add(4)  
    tree.add(5)  
    tree.add(6)  
    tree.add(7)  
    tree.add(8)  
    tree.add(9)  
    print('---广度遍历---')  
    tree.breath_travle()  
    print("")  
    print('---深度遍历(先序)---')  
    tree.preorder(tree.root)  
    print("")  
    print('---深度遍历(中序---')  
    tree.inorder(tree.root)  
    print("")  
    print('---深度遍历(后序---')  
    tree.postorder(tree.root)  
        print("")  
# result  
# ---广度遍历---  
# 0 1 2 3 4 5 6 7 8 9  
# ---深度遍历(先序)---  
# 0 1 3 7 8 4 9 2 5 6  
# ---深度遍历(中序---  
# 7 3 8 1 9 4 0 5 2 6  
# ---深度遍历(后序---  
# 7 8 3 9 4 1 5 6 2 0  

最后

如果你看完了全部,那么恭喜你!!!
接下来这是我写的堆排序的理解,希望能对你有所帮助。

共有评论(0)

登陆即可评论哦