二叉树

基础知识

树(Tree)是一种非线性结构,用来模拟具有树状结构性质的数据集合。它是由n(n>0)个有限结点组成一个具有层次关系的集合。树是递归结构,在树的定义中又用到了树的概念。

基本术语
  • 树结点:包含一个数据元素及若干指向子树的分支;
  • 孩子结点(子结点):结点的子树的根称为该结点的孩子;
  • 双亲结点(父结点):B结点是A结点的孩子,则A结点是B结点的双亲;
  • 兄弟结点:同一双亲的孩子结点;
  • 堂兄结点:同一层上结点;
  • 结点层次:根结点的层定义为1;根的孩子为第二层结点,依此类推;
  • 树的高(深)度:树中最大的结点层;
  • 结点的度:结点子树的个数;
  • 树的度:树中最大的结点度;
  • 叶子结点:也叫终端结点,是度为0的结点;
  • 分枝结点:度不为0的结点(非终端结点);
  • 森林:互不相交的树集合;
    有序树:子树有序的树,如:家族树; 无序树:不考虑子树的顺序
性质
  • 每个节点有零个或多个子节点;
  • 没有父节点的节点称为根节点;
  • 每一个非根节点有且只有一个父节点;
  • 除了根节点外,每个子节点可以分为多个不相交的子树;
  • 树里面没有环路(cycle)。
二叉树

二叉树(Binary tree)是每个节点最多只有两个分支(即不存在分支度大于2的节点)的树结构。通常分支被称作“左子树”或“右子树”。二叉树的分支具有左右次序,不能随意颠倒。二叉树可以为空。

二叉树的遍历

深度优先遍历(Depth First Search,DFS):沿着树的深度遍历树的节点,尽可能深的搜索树的分支。

  • 前序遍历:NLR,根结点->左子树->右子树;
  • 中序遍历:LNR,左子树->根结点->右子树;
  • 后续遍历:LRN,左子树->右子树->根结点。

广度优先遍历(Breadth First Search,BFS;也叫层次遍历,level order):是从根节点开始,沿着树的宽度遍历树的节点。如果所有节点均被访问,则算法中止。

Python建立二叉树及实现各种遍历方法
二叉树结点类
class BinaryNode(object):
    """二叉树节点类"""
    def __init__(self, item, left=None, right=None):
        self.item = item
        self.left = left
        self.right = right
二叉树类

其中包含二叉树的常用操作和七种遍历方法。不做要求的情况下,使用递归的方式实现遍历最简单。

class BinaryTree(object):
    """二叉树及几种遍历方法"""
    def __init__(self):
        self.root = None
        self.bi_list = []  # 使用队列存放二叉树的层次节点信息

    def is_empty(self):
        return self.root is None

    def add(self, item):
        """依次为二叉树添加节点(从上至下,从左至右)"""
        node = BinaryNode(item)
        if self.is_empty():
            self.root = node
            self.bi_list.append(node)
        else:
            tmp_node = self.bi_list[0]
            if tmp_node.left is None:
                tmp_node.left = node
                self.bi_list.append(node)
            else:
                tmp_node.right = node
                self.bi_list.append(node)
                self.bi_list.pop(0)

    def pre_order(self, root):
        if root is None:
            return
        print(root.item)
        self.pre_order(root.left)
        self.pre_order(root.right)

    def in_order(self, root):
        if root is None:
            return
        self.in_order(root.left)
        print(root.item)
        self.in_order(root.right)

    def post_order(self, root):
        if root is None:
            return
        self.post_order(root.left)
        self.post_order(root.right)
        print(root.item)

    def level_order(self, root):
        """层次遍历,也叫广度优先搜索(Breadth-first search)。
        采用队列实现。"""
        if root is None:
            return
        queue = []
        queue.append(root)
        while queue:
            node = queue.pop(0)
            print(node.item)
            # 如果孩子节点不为空,那么从左至右添加进来
            if node.left is not None:
                queue.append(node.left)
            if node.right is not None:
                queue.append(node.right)

    def pre_order_stack(self, root):
        """先序遍历的非递归实现。
        使用栈"""
        if root is None:
            return
        stack = []
        node = root
        while node or stack:
            while node:
                print(node.item)
                stack.append(node)
                node = node.left
            node = stack.pop()
            node = node.right

    def in_order_stack(self, root):
        """中序遍历的非递归实现。
        使用栈"""
        if root is None:
            return
        stack = []
        node = root
        while node or stack:
            while node:
                stack.append(node)
                node = node.left
            node = stack.pop()
            print(node.item)
            node = node.right

    def post_order_stack(self, root):
        """后序遍历的非递归实现。
        使用栈"""
        if root is None:
            return
        stack1, stack2 = [], []
        stack1.append(root)
        while stack1:
            # 此循环为了找出后续遍历的逆序,存入stack2中
            # 先将当前节点拿出来存入stack2中
            node = stack1.pop()
            stack2.append(node)
            if node.left is not None:
                # 若左孩子非空,先入栈stack1(先入后出,所以是逆序)
                stack1.append(node.left)
            if node.right is not None:
                # 若右孩子非空,入栈stack1
                stack1.append(node.right)
        for i in stack2[::-1]:
            print(i.item)

    def height(self, root):
        """递归的求二叉树的最大高度。从叶子结点为‘0层’依次往上数"""
        if root is None:
            return 0
        lheight = self.height(root.left)
        rheight = self.height(root.right)
        return max(lheight + 1, rheight + 1)
def test():
    BT = BinaryTree()
    print('二叉树是否为空:', BT.is_empty())
    print('依次为二叉树添加10个节点...')
    for i in range(10):
        BT.add(i + 1)
    print('前序遍历')
    BT.pre_order(BT.root)
    print('中序遍历')
    BT.in_order(BT.root)
    print('后序遍历')
    BT.post_order(BT.root)
    print('前序遍历,非递归方式')
    BT.pre_order_stack(BT.root)
    print('中序遍历,非递归方式')
    BT.in_order_stack(BT.root)
    print('后序遍历,非递归方式')
    BT.post_order_stack(BT.root)
    print('层次遍历')
    BT.level_order(BT.root)
    print('二叉树的最大高度:', BT.height(BT.root))
二叉搜索树

二叉搜索树是一种节点值之间具有一定数量级次序的二叉树,对于树中每个节点:

  • 若其左子树存在,则其左子树中每个节点的值都不大于该节点值;
  • 若其右子树存在,则其右子树中每个节点的值都不小于该节点值。
    在这里插入图片描述
树节点定义
# tree node definition
class Node(object):
    def __init__(self, value, lchild=None, rchild=None):
        self.value = value
        self.lchild = lchild
        self.rchild = rchild
树定义
# tree definition
class Tree(object):
    def __init__(self, root=None):
        self.root = root

    # node in-order traversal(LDR)
    def traversal(self):
        traversal(self.root)

    # insert node
    def insert(self, value):
        self.root = insert(self.root, value)

    # delete node
    def delete(self, value):
        self.root = delete(self.root, value)
模块中对树结构中的函数进行实现
# node in-order traversal(LDR)
def traversal(node):
    if not node:
        return
    traversal(node.lchild)
    print(node.value,end=' ')
    traversal(node.rchild)

# insert node
def insert(root, value):
    if not root:
        return Node(value)
    if value < root.value:
        root.lchild = insert(root.lchild, value)
    elif value > root.value:
        root.rchild = insert(root.rchild, value)
    return root

# delete node
def delete(root, value):
    if not root:
        return None
    if value < root.value:
        root.lchild = delete(root.lchild, value)
    elif value > root.value:
        root.rchild = delete(root.rchild, value)
    else:
        if root.lchild and root.rchild:  # degree of the node is 2
            target = root.lchild  # find the maximum node of the left subtree
            while target.rchild:
                target = target.rchild
            root = delete(root, target.value)
            root.value = target.value
        else:  # degree of the node is [0|1]
            root = root.lchild if root.lchild else root.rchild
    return root
测试代码与输出
if __name__ == '__main__':
    arr = [5, 3, 4, 0, 2, 1, 8, 6, 9, 7]
    T = Tree()
    for i in arr:
        T.insert(i)
    print('BST in-order traversal------------------')
    T.traversal()
    print('\ndelete test------------------')
    for i in arr[::-1]:
        print('after delete',i,end=',BST in-order is = ')
        T.delete(i)
        T.traversal()
        print()
输出结果为
BST in-order traversal------------------
0 1 2 3 4 5 6 7 8 9 
delete test------------------
after delete 7,BST in-order is = 0 1 2 3 4 5 6 8 9 
after delete 9,BST in-order is = 0 1 2 3 4 5 6 8 
after delete 6,BST in-order is = 0 1 2 3 4 5 8 
after delete 8,BST in-order is = 0 1 2 3 4 5 
after delete 1,BST in-order is = 0 2 3 4 5 
after delete 2,BST in-order is = 0 3 4 5 
after delete 0,BST in-order is = 3 4 5 
after delete 4,BST in-order is = 3 5 
after delete 3,BST in-order is = 5 
after delete 5,BST in-order is = 
平衡二叉树

平衡二叉树的提出就是为了保证树不至于太倾斜,尽量保证两边平衡。因此它的定义如下:

  • 平衡二叉树要么是一棵空树
  • 要么保证左右子树的高度之差不大于 1
  • 子树也必须是一颗平衡二叉树
    也就是说,树的两个左子树的高度差别不会太大。

漫画版了解二叉查找树二叉平衡树和红黑树

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值