Python3&数据结构之二叉树

实现二叉树以及遍历

在计算机科学中,二叉树是每个结点最多有两个子树的树结构。通常子树被称作“左子树”(left subtree)和“右子树”(right subtree)。二叉树常被用于实现二叉查找树和二叉堆。

二叉树是递归定义的,其结点有左右子树之分,逻辑上二叉树有五种基本形态:

(1)空二叉树——如图(a);

(2)只有一个根结点的二叉树——如图(b);

(3)只有左子树——如图(c);

(4)只有右子树——如图(d);

(5)完全二叉树——如图(e)。

树和二叉树有两个主要差别:

(1)树中结点的最大度数没有限制,而二叉树结点的最大度数为2;

(2)树的结点无左、右之分,而二叉树的结点有左、右之分。

二叉树的性质:

(1)二叉树第i层上的结点数目最多为2^(i-1)(i>=1);

(2)深度为k的二叉树至多有(2^k)-1个结点(k>=1);

(3)包含n个结点的二叉树的高度至少为(logn)+1;(log默认为以2为底);

(4)在任意一棵二叉树中,若终端结点的个数为n0,度为2的结点数为n2,则n0=n2+1。

二叉树的种类:

(1)满二叉树:如果二叉树中所有分支节点的度都为2,则称它为一棵满二叉树。满二叉树是一般二叉树的子集;

(2)完全二叉树:对于一棵高度为h的二叉树,如果其第0层至第h-1层的结点都满(也就是说,对所有0≤i≤h-1,第i层有2^i个结点)。如果最下一层的结点不满,则所有结点在最左边连续排列,空位都在右边。这样的二叉树就是一棵完全二叉树;

(3)平衡二叉树:平衡二叉树(Self-balancing binary search tree)又被称为AVL树(有别于AVL算法),且具有以下性质:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。平衡二叉树的常用实现方法有红黑树、AVL、替罪羊树、Treap、伸展树等。 最小二叉平衡树的节点的公式如下 F(n)=F(n-1)+F(n-2)+1 这个类似于一个递归的数列,可以参考Fibonacci(斐波那契)数列,1是根节点,F(n-1)是左子树的节点数量,F(n-2)是右子树的节点数量。

对于平衡二叉树要特别注意的是,不要求非叶节点都有两个子结点,仅要求两个子树的高度差的绝对值不超过1,或者为空树。

关于遍历:

设L、D、R分别表示遍历左子树、访问根结点和遍历右子树, 则对一棵二叉树的遍历有三种情况:DLR(称为先根次序遍历),LDR(称为中根次序遍历),LRD (称为后根次序遍历)。

具体的代码部分:

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

class Tree(object):
    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 []
        res = [root.item]
        left_item = self.preorder(root.child1)
        right_item = self.preorder(root.child2)
        return res + left_item + right_item

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

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

if __name__ == '__main__':
    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))

参考文献:

[1] https://baike.baidu.com/item/%E4%BA%8C%E5%8F%89%E6%A0%91/1602879?fr=aladdin

[2] https://blog.csdn.net/mxz19901102/article/details/80071864

猜你喜欢

转载自blog.csdn.net/qq_38575545/article/details/84888860