【数据结构与算法】002—树与二叉树(Python)

概念

树是一类重要的非线性数据结构,是以分支关系定义的层次结构

定义:

树(tree)是n(n>0)个结点的有限集T,其中: 有且仅有一个特定的结点,称为树的根(root)

当n>1时,其余结点可分为m(m>0)个互不相交的有限集T1,T2,……Tm,其中每一个集合本身又是一棵树,称为根的子树(subtree)

特点: 树中至少有一个结点——根 树中各子树是互不相交的集合

基本术语

  • 结点(node)——表示树中的元素,包括数据项及若干指向其子树的分支

  • 结点的度(degree)——结点拥有的子树数 叶子(leaf)——度为0的结点

  • 孩子(child)——结点子树的根称为该结点的孩子

  • 双亲(parents)——孩子结点的上层结点叫该结点的~

  • 兄弟(sibling)——同一双亲的孩子

  • 树的度——一棵树中最大的结点度数

  • 结点的层次(level)——从根结点算起,根为第一层,它的孩子为第二层……

  • 深度(depth)——树中结点的最大层次数

  • 森林(forest)——m(m0)棵互不相交的树的集合



二叉树

二叉树是有限个元素的集合,该集合或者为空、或者有一个称为根节点(root)的元素及两个互不相交的、分别被称为左子树和右子树的二叉树组成。

  • 二叉树的每个结点至多只有二棵子树(不存在度大于2的结点),二叉树的子树有左右之分,次序不能颠倒。
  • 二叉树的第i层至多有2^{i-1}个结点
  • 深度为k的二叉树至多有2^k-1个结点;
  • 对任何一棵二叉树T,如果其终端结点数为N0,度为2的结点数为N2,则N0=N2+1

遍历二叉树

  • 前序遍历
    若树为空,则空操作返回。否则,先访问根节点,然后前序遍历左子树,再前序遍历右子树。(W)型 (中 左 右)
  • 中序遍历
    若树为空,则空操作返回。否则,从根节点开始(注意并不是先访问根节点),中序遍历根节点的左子树,然后是访问根节点,最后中序遍历根节点的右子树。(M)型,(左 中 右)
  • 后续遍历
    若树为空,则空操作返回。否则,从左到右先叶子后节点的方式遍历访问左右子树,最后访问根节点。(左右中)逆时针型 (左 右 中)
  • 层序遍历
    若树为空,则空操作返回。否则,从树的第一层,也就是根节点开始访问,从上到下逐层遍历,在同一层中,按从左到右的顺序结点逐个访问。


实现方法

class Node:
    def __init__(self,item):
        self.item = item
        self.child1 = None
        self.child2 = None


class Tree:
    def __init__(self):
        self.root = None

    def add(self, item):
        node = Node(item)
        if self.root is None:
            self.root = node
        else:
            q = [self.root]

            while True:
                pop_node = q.pop(0)
                if pop_node.child1 is None:
                    pop_node.child1 = node
                    return
                elif pop_node.child2 is None:
                    pop_node.child2 = node
                    return
                else:
                    q.append(pop_node.child1)
                    q.append(pop_node.child2)

    def traverse(self):  # 层次遍历
        if self.root is None:
            return None
        q = [self.root]
        res = [self.root.item]
        while q != []:
            pop_node = q.pop(0)
            if pop_node.child1 is not None:
                q.append(pop_node.child1)
                res.append(pop_node.child1.item)

            if pop_node.child2 is not None:
                q.append(pop_node.child2)
                res.append(pop_node.child2.item)
        return res

    def preorder(self,root):  # 先序遍历
        if root is None:
            return []
        result = [root.item]
        left_item = self.preorder(root.child1)
        right_item = self.preorder(root.child2)
        return result + left_item + right_item

    def inorder(self,root):  # 中序序遍历
        if root is None:
            return []
        result = [root.item]
        left_item = self.inorder(root.child1)
        right_item = self.inorder(root.child2)
        return left_item + result + right_item

    def postorder(self,root):  # 后序遍历
        if root is None:
            return []
        result = [root.item]
        left_item = self.postorder(root.child1)
        right_item = self.postorder(root.child2)
        return left_item + right_item + result

t = Tree()
for i in range(10):
    t.add(i)
print('层序遍历:',t.traverse())
print('先序遍历:',t.preorder(t.root))
print('中序遍历:',t.inorder(t.root))
print('后序遍历:',t.postorder(t.root))
层序遍历: [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]

猜你喜欢

转载自www.cnblogs.com/xianeri/p/10177333.html