Python学习------数据结构应用(树)

 一、Python中树的定义:一棵树由根和其他子树组成,这些子树也是树。

二、python中树的实现:

1、python中可以用列表表示树,列表中有三个元素[根,左孩子,右孩子],左右孩子还是一个列表,也是由三个元素组成。

例如['a', ['b', 'c', []], []]:这棵数根节点是'a',左孩子是['b', 'c', []],右孩子是[],左孩子也是一棵树,树根为'b',左孩子是'c',右孩子是[]。

def binary_tree(root):
    """创建一个新树,root为根节点"""
    return [root, [], []]

def insert_left(root, new_branch):
    """ 插入左子树,new_branch左子树的根节点。

        如果原来的树没有左子树,则直接插入根节点;
        如果原来的树存在左子树,则原来的子树会变成新子树的左节点
    """
    t = root.pop(1)
    if len(t) > 1:  # 存在原来的左子树
        root.insert(1, [new_branch, t, []])
    else:
        root.insert(1, [new_branch, [], []])
    return root

def insert_right(root, new_branch):
    """ 插入右子树,new_branch右子树的根节点。

        如果原来的树没有右子树,则直接插入根节点;
        如果原来的树存在右子树,则原来的子树会变成新子树的右节点
    """
    t = root.pop(2)
    if len(t) > 1:  # 存在原来的右子树
        root.insert(2, [new_branch, [], t])
    else:
        root.insert(2, [new_branch, [], []])
    return root

def get_root_val(root):
    """返回根节点的值"""
    return root[0]

def set_root_val(root, new_val):
    """修改根节点的值"""
    root[0] = new_val

def get_left_child(root):
    """返回左子树列表"""
    return root[1]

def get_right_child(root):
    """返回右子树列表"""
    return root[2]

# 测试
tree = binary_tree('a')
insert_left(tree, 'b')
insert_right(tree, 'c')
insert_right(get_right_child(tree), 'd')
insert_left(get_right_child(tree), 'e')
print(tree)

2、python中还可以用Nodes and References表示树,这种思想一般通过定义类来实现:

class BinaryTree:
    """通过类来实现树"""
    def __init__(self, root):
        """初始化树,root为根节点"""
        self.key = root
        self.left_child = None
        self.right_child = None

    def insert_left(self, new_node):
        """ 插入左子树:new_node为左子树的根节点

            如果原来的树不存在左子树,则new_node成为root树的左子树
            如果原来的树存在左子树,则原来的左子树变为以new_node为根节点的左子树
        """
        if self.left_child:
            t = BinaryTree(new_node)
            t.left_child = self.left_child
            self.left_child = t
        else:
            self.left_child = BinaryTree(new_node)

    def insert_right(self, new_node):
        """ 插入右子树:new_node为右子树的根节点

            如果原来的树不存在右子树,则new_node成为root树的右子树
            如果原来的树存在右子树,则原来的右子树变为以new_node为根节点的右子树
        """
        if self.right_child:
            t = BinaryTree(new_node)
            t.right_child = self.right_child
            self.right_child = t
        else:
            self.right_child = BinaryTree(new_node)

    def get_right_child(self):
        """得到root树的右子树"""
        return self.right_child

    def get_left_child(self):
        """得到root树的左子树"""
        return self.left_child

    def set_root_val(self,obj):
        """修改root树的根节点的值"""
        self.key = obj

    def get_root_val(self):
        """得到root树的根节点的值"""
        return self.key

# 测试
tree = BinaryTree('a')
tree.insert_left('b')
tree.insert_right('c')
tree.get_right_child().insert_right('f')
print(tree)

三、树的遍历

树的遍历分为三种:先序遍历,中序遍历,后序遍历

先序遍历(preorder,根左右

def preorder(tree):
    if tree:
        print(tree.get_root_val())
        preorder(tree.get_left_child())
        preorder(tree.get_right_child())

中序遍历(inorder,左根右),

def inorder(tree):
    if tree:
        inorder(tree.get_left_child())
        print(tree.get_root_val)
        inorder(tree.get_right_child())

后序遍历(postorder,左右根)

def postorder(tree):
    if tree:
        postorder(tree.get_left_child())
        postorder(tree.get_right_child())
        print(tree.get_root_val)

四、二叉搜索树

二叉搜索树有一个重要的特性:parent的key值比左结点大,比右结点小。

 

# 二叉搜索树 BST
class TreeNode:
    """BST的结点类"""
    def __init__(self, value, left=None, right=None):
        """初始化结点"""
        self.value = value
        self.left_child = left
        self.right_child = right

class BST:
    """二叉搜索树的类"""
    def __init__(self):
        """初始化BST,root树为空"""
        self.root = None

    def insert(self, value, root):
        """插入结点"""
        if not root:  # 该节点为根节点
            root = TreeNode(value)
        elif value < root.value:
            root.left_child = self.insert(value, root.left_child)
        elif value > root.value:
            root.right_child = self.insert(value, root.right_child)
        return root

    def delete(self, root, value):
        """
        删除二叉搜索树中值为value的点:
        
        若找到,则删除,返回该节点;
        若没找到,则返回False
        """
        if root:
            if value < root.value:
                root.left_child = self.delete(root.left_child, value)
            elif value > root.value:
                root.right_child = self.delete(root.right_child, value)
            # 当value == root.value时,分为三种情况:只有左子树或者只有右子树、有左右子树、即无左子树又无右子树
            else:
                if root.left_child and root.right_child:
                    # 既有左子树又有右子树,则需找到右子树中最小值节点
                    temp = self.findMin(root.right_child)
                    root.value = temp.value
                    # 再把右子树中最小值节点删除
                    root.right_child = self.delete(root.right_child, temp.value)
                elif root.right_child:
                    # 只有右子树
                    root = root.right_child
                elif root.left_child:
                    # 只有左子树
                    root = root.left_child
                else:
                    # 左右子树都为空
                    root = None
            return root
        else:
            return False

    def inorder(self, root):
        """中序遍历BST"""
        if root:
            self.inorder(root.left_child)
            print(root.value, end=' ')
            self.inorder(root.right_child)
        else:
            print(None, end='')

    def depth(self, root):
        """返回树的深度"""
        if root:
            return 1 + max(self.depth(root.left_child), self.depth(root.right_child))
        else:
            return 0

    def search(self, value, root):
        """ 二叉搜索树查询操作:
        if not root:
            root = self.root

            根据所给的value,查询树中是否存在。
            如存在,则返回该结点;若不存在,则返回False
        """
        if not root:
            return False
        if root.value == value:
            return root
        elif value < root.value:
            return self.search(value, root.left_child)
        elif value > root.value:
            return self.search(value, root.right_child)

    def findMin(self, root):
        """
        查找二叉搜索树中最小值
        
        返回最小值结点
        """
        if root.left_child:
            return self.findMin(root.left_child)
        else:
            return root

    def findMax(self, root):
        """
        查找二叉搜索树中最大值
        返回最大值结点
        """
        if root.right_child:
            return self.findMax(root.right_child)
        else:
            return root


def main():
    """测试BST"""
    root = BST()
    root.root = root.insert(7, root.root)
    root.root = root.insert(4, root.root)
    root.root = root.insert(5, root.root)
    root.root = root.insert(10, root.root)
    root.root = root.insert(9, root.root)
    root.root = root.insert(13, root.root)
    root.root = root.insert(12, root.root)
    root.inorder(root.root)
    print('深度:', root.depth(root.root))
    print('最大值:', root.findMax(root.root).value)
    print('最小值:', root.findMin(root.root).value)
    print('搜索:', root.search(8, root.root))
    print('搜索:', root.search(12, root.root).value)

    print('delete')
    topo = """
                7
            4       10
              5   9     13
                      12
    测试的时候建议先画好删除以后的图,然后对照着图和结果检查
    """
    print('树图', topo)
    root.root = root.delete(root.root, 6)  # 找不到
    root.inorder(root.root)
    print()
    root.root = root.delete(root.root, 9)  # 左右子女都没有
    root.inorder(root.root)
    print()
    root.root = root.delete(root.root, 13)  # 只有左子女
    root.inorder(root.root)
    print()
    root.root = root.delete(root.root, 4)  # 只有右子女
    root.inorder(root.root)
    print()
    root.root = root.delete(root.root, 7)  # 左右子女都有
    root.inorder(root.root)

if __name__ == "__main__":
    main()

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值