Python数据结构之二叉排序树的定义、查找、插入、构造、删除

Python数据结构之二叉排序树

一、定义

二叉排序树(Binary Search Tree,BST),也称为二叉查找树或二叉搜索树,是一种基于二叉树的数据结构,其中每个节点都包含一个键值,且满足:

  • 左子树中所有节点的键值均小于当前节点;
  • 右子树中所有节点的键值均大于当前节点;

这是一种自平衡的数据结构,可以快速地进行查找、插入、删除等操作。

二、查找

查找操作是在二叉排序树中查找某个键值对应的节点。查找过程可以用递归或循环实现。

递归实现

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

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

    def search(self, val, node):
        if node is None or node.val == val:
            return node
        elif node.val > val:
            return self.search(val, node.left)
        else:
            return self.search(val, node.right)

这里在BST类中定义了一个search方法,采用了递归的方式。如果当前节点为空或者当前节点的值等于要查找的值,则返回当前节点。否则,如果当前节点的值大于要查找的值,则向左子树递归查找;如果当前节点的值小于要查找的值,则向右子树递归查找。

循环实现

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

    def search(self, val):
        node = self.root
        while node is not None and node.val != val:
            if node.val > val:
                node = node.left
            else:
                node = node.right
        return node

这里在BST类中定义了一个search方法,采用了循环的方式。首先将node指向BST的根节点,然后在循环中判断node是否为空或者node的值是否等于要查找的值。如果是,则返回node;否则,如果node的值大于要查找的值,则将node指向node的左子节点;如果node的值小于要查找的值,则将node指向node的右子节点。

三、插入

插入操作是在二叉排序树中插入一个键值对应的节点。插入过程可以用递归或循环实现。

递归实现

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

    def insert(self, val, node):
        if node is None:
            node = TreeNode(val)
        elif node.val > val:
            node.left = self.insert(val, node.left)
        elif node.val < val:
            node.right = self.insert(val, node.right)
        return node

这里在BST类中定义了一个insert方法,采用了递归的方式。首先判断当前节点是否为空,如果是,则创建一个新的节点并返回;否则,如果当前节点的值大于要插入的值,则递归插入到左子树;如果当前节点的值小于要插入的值,则递归插入到右子树。

示例:

tree = BST()
tree.root = tree.insert(2, tree.root)
tree.insert(1, tree.root)
tree.insert(3, tree.root)

这里创建了一棵二叉排序树,然后依次插入了3个节点,其值分别为2、1、3。

循环实现

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

    def insert(self, val):
        node = self.root
        prev = None
        while node is not None:
            prev = node
            if node.val > val:
                node = node.left
            elif node.val < val:
                node = node.right
            else:
                return self.root
        new_node = TreeNode(val)
        if prev is None:
            self.root = new_node
        elif prev.val > val:
            prev.left = new_node
        else:
            prev.right = new_node
        return self.root

这里在BST类中定义了一个insert方法,采用了循环的方式。首先将node指向BST的根节点,prev指向node的父节点,然后在循环中判断node是否为空。如果是,则创建一个新的节点并根据val的大小插入到prev的左子节点或右子节点。

示例:

tree = BST()
tree.insert(2)
tree.insert(1)
tree.insert(3)

这里创建了一棵二叉排序树,然后依次插入了3个节点,其值分别为2、1、3。

四、构造

构造操作是从一个键值的列表中构造出一棵二叉排序树。构造过程可以用递归或循环实现。

递归实现

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

    def construct(self, values):
        for val in values:
            self.root = self.insert(val, self.root)

这里在BST类中定义了一个construct方法,采用了递归的方式。首先遍历values中的每一个值,然后递归插入到BST中。

示例:

tree = BST()
tree.construct([2, 1, 3])

这里创建了一棵二叉排序树,其值分别为2、1、3。

循环实现

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

    def construct(self, values):
        for val in values:
            new_node = TreeNode(val)
            node = self.root
            prev = None
            while node is not None:
                prev = node
                if node.val > val:
                    node = node.left
                elif node.val < val:
                    node = node.right
                else:
                    break
            if prev is None:
                self.root = new_node
            elif prev.val > val:
                prev.left = new_node
            else:
                prev.right = new_node

这里在BST类中定义了一个construct方法,采用了循环的方式。首先遍历values中的每一个值,然后依次插入到BST中。

示例:

tree = BST()
tree.construct([2, 1, 3])

这里创建了一棵二叉排序树,其值分别为2、1、3。

五、删除

删除操作是在二叉排序树中删除某个键值对应的节点。主要包含3种情况:

  • 要删除的节点没有子节点;
  • 要删除的节点只有一个子节点;
  • 要删除的节点有两个子节点;

情况一和情况二

情况一和情况二的解决方法相同。如果要删除的节点没有子节点,则直接将其删除;如果要删除的节点只有一个子节点,则将其子节点移到其原来的位置。这里的代码实现比较简单,这里只展示递归实现。

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

    def delete(self, val, node):
        if node is None:
            return node
        if node.val > val:
            node.left = self.delete(val, node.left)
        elif node.val < val:
            node.right = self.delete(val, node.right)
        else:
            if node.left is None:
                return node.right
            elif node.right is None:
                return node.left
            else:
                min_node = self.find_min(node.right)
                node.val = min_node.val
                node.right = self.delete(min_node.val, node.right)
        return node

    def find_min(self, node):
        while node.left is not None:
            node = node.left
        return node

这里在BST类中定义了一个delete方法,采用了递归的方式。如果当前节点为空,则返回;如果当前节点的值大于要删除的值,则继续递归删除它的左子节点;如果当前节点的值小于要删除的值,则继续递归删除它的右子节点;如果当前节点的值等于要删除的值,则判断当前节点是否有左右子节点。如果没有子节点,则直接返回None;如果只有一个子节点,则返回这个子节点;如果有两个子节点,则找到右子树中最小的节点替换当前节点的值,并递归删除这个最小节点。

情况三

情况三需要特殊处理。首先找到要删除的节点的右子树中最小的节点代替要删除的节点,并从右子树中递归删除这个最小节点。这里的代码实现比较复杂,这里只展示递归实现。

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

    def delete(self, val, node):
        if node is None:
            return node
        if node.val > val:
            node.left = self.delete(val, node.left)
        elif node.val < val:
            node.right = self.delete(val, node.right)
        else:
            if node.left is None:
                return node.right
            elif node.right is None:
                return node.left
            else:
                min_node = self.find_min(node.right)
                node.val = min_node.val
                node.right = self.delete(min_node.val, node.right)
        return node

    def find_min(self, node):
        while node.left is not None:
            node = node.left
        return node

这里在BST类中定义了一个delete方法,采用了递归的方式。如果当前节点为空,则返回;如果当前节点的值大于要删除的值,则继续递归删除它的左子节点;如果当前节点的值小于要删除的值,则继续递归删除它的右子节点;如果当前节点的值等于要删除的值,则判断当前节点是否有左右子节点。如果没有子节点,则直接返回None;如果只有一个子节点,则返回这个子节点;如果有两个子节点,则找到右子树中最小的节点替换当前节点的值,并递归删除这个最小节点。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python数据结构之二叉排序树的定义、查找、插入、构造、删除 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • CSP-何以包邮?

    题目描述 新学期伊始,适逢顿顿书城有购书满 x 元包邮的活动,小 P 同学欣然前往准备买些参考书。一番浏览后,小 P 初步筛选出 n 本书加入购物车中,其中第 i 本(1≤i≤n)的价格为 ai 元。考虑到预算有限,在最终付款前小 P 决定再从购物车中删去几本书(也可以不删),使得剩余图书的价格总和 m 在满足包邮条件(m≥x)的前提下最小。 试帮助小 P …

    算法与数据结构 2023年5月11日
    00
  • Java数据结构之加权无向图的设计实现

    Java数据结构之加权无向图的设计实现 前言 在计算机科学中,图(Graph)作为一种基本数据结构,被广泛应用于各种领域,如网络流、图像处理、计算机视觉等。本文将介绍加权无向图(Weighted Undirected Graph)的设计实现,涉及图的存储、添加边、获取特定节点的相邻节点、计算最短路径等。 设计实现 存储结构 加权无向图可以用一个邻接表数组存储…

    数据结构 2023年5月17日
    00
  • 莫比乌斯反演,欧拉反演学习笔记

    (未更完) 我算法中也就差点数论没学了,这几周卷了,学了一下,分享一下啊。 我会讲得详细一点,关于我不懂得地方,让新手更容易理解。 学习反演有很多定义啥的必须要记的,学的时候容易崩溃,所以希望大家能坚持下来。   第一个定义: $\lfloor x\rfloor$:意思是小于等于 $x$ 的最大整数。 数论分块 学习反演之前,要先学习一些边角料,先来看数论分…

    算法与数据结构 2023年4月17日
    00
  • 浅析Java 数据结构常用接口与类

    浅析 Java 数据结构常用接口与类 本文主要介绍 Java 中常用的数据结构接口和类,可以帮助读者了解和掌握常见的数据结构以及它们的实现方式,从而在日后的开发中使用它们,提高代码的效率和质量。 List 接口 List 接口是 Java 中常用的数据结构接口之一,它代表了一个有序的集合,集合中的每一个元素都可以通过其索引进行访问。List 接口的一些常用方…

    数据结构 2023年5月17日
    00
  • 蒙特卡罗方法:当丢失确定性时的处理办法

    一、简介   蒙特卡罗(Monte Carlo),也可翻译为蒙特卡洛,只是不同的音译选词,比较常用的是蒙特卡罗。是摩洛哥的一片城区,以拥有豪华赌场闻名,蒙特卡罗方法是基于概率的。基本思想:如果你想预测一件事情的结果,你只要把随机生成的各种输入值,把这件事模拟很多遍,根据模拟出的结果就可以看到事情的结果大致是什么情况。蒙特卡罗算法是基于蒙特卡罗方法的算法。 二…

    算法与数据结构 2023年4月17日
    00
  • 一些常见的字符串匹配算法

    作者:京东零售 李文涛 一、简介 1.1 Background 字符串匹配在文本处理的广泛领域中是一个非常重要的主题。字符串匹配包括在文本中找到一个,或者更一般地说,所有字符串(通常来讲称其为模式)的出现。该模式表示为p=p[0..m-1];它的长度等于m。文本表示为t=t[0..n-1],它的长度等于n。两个字符串都建立在一个有限的字符集上。 一个比较常见…

    算法与数据结构 2023年4月25日
    00
  • C语言数据结构之复杂链表的拷贝

    C语言数据结构之复杂链表的拷贝 什么是复杂链表 在了解如何拷贝复杂链表之前,首先需要知道什么是复杂链表。复杂链表是由多个节点组成的链表,每个节点除了包含普通链表节点的值和指向下一个节点的指针外,还包含一个指向链表中的任意一个节点的指针。因此,每个节点有两个指针:一个指向下一个节点,一个指向任意一个节点。 复杂链表示意图如下: +—+ +—+ +—…

    数据结构 2023年5月17日
    00
  • Python数据结构与算法之链表定义与用法实例详解【单链表、循环链表】

    Python数据结构与算法之链表定义与用法实例详解 什么是链表? 链表是一种常见的数据结构,它由一个个的节点组成,每个节点包含两部分,一部分存储数据,一部分存储下一个节点在哪里的指针。通过节点之间的指针,就可以将节点串起来,形成一个链表。 链表和数组是两种截然不同的数据结构,数组的元素在内存中是连续存储的,而链表的节点却可以分散在内存的不同位置,这也是链表灵…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部