欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

数据结构各种树总结

程序员文章站 2022-07-12 22:18:49
...

1. 二叉树(Binary Tree)

(1)定义

每个节点最多只有两个子节点,没有子节点的节点称之为叶子节点,第一个节点为根节点。

数据结构各种树总结

(2)二叉树的性质

① 我们将节点用数组的形式进行保存,比如是tree, tree[0]就代表根节点。假设父节点是tree[n],左节点为tree[n*2+1], 右节点为tree[n*2+2]。

② 每一层的节点都是满的树我们称为满二叉树(Full Binary Tree),比如下面图a。除了最后一层不满之外,其它层都是满的的树称为完全二叉树(Complete Binary Tree),如图b。

数据结构各种树总结

③ 在一棵满二叉树中,我们假设根节点是第0层,则每一层的节点个数为2^n,第n层之前所有节点个数为(2^n) - 1。

(3)二叉树的各种基本操作

二叉树的创建,先序遍历,中序遍历,后序遍历

from typing import List

class TreeNode:
    def __init__(self, val: int):
        self.val = val
        self.left = None
        self.right = None

class Tree:
    def __init__(self):
        self.root = None
    # 给你一个数组,去创建一颗二叉树
    def create(self, nums: List[int]) -> None:
        tree_nodes = []
        for num in nums:
            if num:
                temp_node = TreeNode(num)
                tree_nodes.append(temp_node)
            else:
                tree_nodes.append(None)
        for i, node in enumerate(tree_nodes):
            if node:
                if i * 2 + 1 < len(nums):
                    node.left = tree_nodes[i * 2 + 1]
                if i * 2 + 2 < len(nums):
                    node.right = tree_nodes[i * 2 + 2]
        self.root = tree_nodes[0]
        return self.root

    # 树的先序遍历,也就是先访问父节点,再访问左节点,再访问右节点
    def pre_order(self, node: TreeNode) -> None:
        if not node:
            return
        print(node.val)
        self.pre_order(node.left)
        self.pre_order(node.right)

    # 树的中序遍历,先访问左节点,再访问父节点,再访问右节点
    def in_order(self, node: TreeNode) -> None:
        if not node:
            return
        self.in_order(node.left)
        print(node.val)
        self.in_order(node.right)

    # 树的后序遍历,先访问右节点,再访问父节点,再访问左节点
    def post_order(self, node: TreeNode) -> None:
        if not node:
            return
        self.post_order(node.right)
        print(node.val)
        self.post_order(node.left)


if __name__ == '__main__':
    test = Tree()
    root = test.create([5,1,4,None,None,3,6])
    test.pre_order(root)
    test.in_order(root)
    test.post_order(root)

2. 二叉搜索树 (Binary Search Tree)

(1)定义

一颗二叉树满足如下性质,则就是一颗二叉搜索树

① 若左子树不为空,则所有的左子树的值都小于父节点的值

② 若右子树不为空,则所有的右子树的值都大于父节点的值。

③ 左右子树也都是二叉搜索树

④ 没有相同值的节点

(2)性质

① 对二叉搜索树进行中序遍历(先遍历左节点,再遍历父节点,再遍历右节点)则得到有序数列。

(3)二叉搜索树的各种操作

① 插入操作

若当前的树为空,则插入的元素为根节点。

若插入的节点小于根节点,则插入到左子树(递归)。

如果插入的节点大于等于根节点,则插入到右子树(递归)。

所有新插入的节点成为叶子节点。

# 插入一个新的节点
    def insert(self, root, val):
        if not root:
            self.root = TreeNode(val)
            return
        if val == root.val:
            return
        if val < root.val:
            if not root.left:
                root.left = TreeNode(val)
            else:
                self.insert(root.left, val)
        else:
            if not root.right:
                root.right = TreeNode(val)
            else:
                self.insert(root.right, val)

② 查询操作

# 查找一个节点是否在这课树中,如果不在则返回False,在的话则返回True
    def search(self, root, val):
        if not root:
            return False
        if val < root.val:
            return self.search(root.left, val)
        elif val > root.val:
            return self.search(root.right, val)
        else:
            return True

③ 创建二叉搜索树

    def create(self, nums):
        for num in nums:
            new_node = TreeNode(num)
            self.insert(self.root, new_node)
        return self.root

④ 中序遍历,可以得到从小到大的list

    def in_order(self, node, rlt):
        if not node:
            return rlt
        self.in_order(node.left, rlt)
        rlt.append(node.val)
        self.in_order(node.right, rlt)

⑤ 删除操作

如果要删除的节点是叶子节点,就直接删除,修改叶子节点的left或者right为None

如果要删除的节点a只有一个子节点b,a节点的父节点是c,那么将c的对应子节点指向b,同时删掉a节点

如果要删除的节点既有左节点又有右节点,那么选择该节点的右子树中最小的那个点的值赋值到该节点,并且删除最小值的那个节点。

如果不理解的话,可以参考这篇博客,里面有详细的图解。

    def delete(self, parent, curr, val):
        # 如果是一颗空树
        if not curr:
            return None
        if val < curr.val:
            self.delete(curr, curr.left, val)
        elif val > curr.val:
            self.delete(curr, curr.right, val)
        else:
            if not curr.left:
                if parent.left == curr:
                    parent.left = curr.right
                else:
                    parent.right = curr.right
                del curr
            elif not curr.right:
                if parent.left == curr:
                    parent.left = curr.left
                else:
                    parent.right = curr.left
                del curr
            else:
                pre_node = curr.right
                if not pre_node.left:
                    curr.val = pre_node.val
                    curr.right = pre_node.right
                    del pre_node
                else:
                    temp_node = curr.right
                    while temp_node.left:
                        pre_node = temp_node
                        temp_node = temp_node.left
                    curr.val = temp_node.val
                    pre_node.left = None
                    del temp_node

 

最后的整体代码:

class TreeNode:
    def __init__(self, val: int):
        self.val = val
        self.left = None
        self.right = None

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

    # 查找一个节点是否在这课树中,如果不在则返回False,在的话则返回True
    def search(self, root, val):
        if not root:
            return False
        if val < root.val:
            return self.search(root.left, val)
        elif val > root.val:
            return self.search(root.right, val)
        else:
            return True

    # 插入一个新的节点
    def insert(self, root, val):
        if not root:
            self.root = TreeNode(val)
            return
        if val == root.val:
            return
        if val < root.val:
            if not root.left:
                root.left = TreeNode(val)
            else:
                self.insert(root.left, val)
        else:
            if not root.right:
                root.right = TreeNode(val)
            else:
                self.insert(root.right, val)

    def create(self, nums):
        for num in nums:
            self.insert(self.root, num)
        return self.root

    def in_order(self, node, rlt):
        if not node:
            return rlt
        self.in_order(node.left, rlt)
        rlt.append(node.val)
        self.in_order(node.right, rlt)

    def delete(self, parent, curr, val):
        # 如果是一颗空树
        if not curr:
            return None
        if val < curr.val:
            self.delete(curr, curr.left, val)
        elif val > curr.val:
            self.delete(curr, curr.right, val)
        else:
            if not curr.left:
                if parent.left == curr:
                    parent.left = curr.right
                else:
                    parent.right = curr.right
                del curr
            elif not curr.right:
                if parent.left == curr:
                    parent.left = curr.left
                else:
                    parent.right = curr.left
                del curr
            else:
                pre_node = curr.right
                if not pre_node.left:
                    curr.val = pre_node.val
                    curr.right = pre_node.right
                    del pre_node
                else:
                    temp_node = curr.right
                    while temp_node.left:
                        pre_node = temp_node
                        temp_node = temp_node.left
                    curr.val = temp_node.val
                    pre_node.left = None
                    del temp_node


if __name__ == '__main__':
    test = BST()
    root = test.create([5,3,2,1,4])
    test.delete(root, root, 3)
    rlt = []
    test.in_order(root, rlt)
    print(rlt)

 

相关标签: 数据结构