python 实现二叉搜索树的四种方法

Python 实现二叉搜索树的四种方法

二叉搜索树(Binary Search Tree,简称BST)是一棵二叉树,它具有以下性质:

  1. 若左子树不为空,则左子树上所有结点的值均小于它的根节点的值;
  2. 若右子树不为空,则右子树上所有结点的值均大于它的根节点的值;
  3. 左、右子树分别也为二叉搜索树;
  4. 没有键值相等的节点;

因其高效性,在排序、查找等问题中,常常使用二叉搜索树来解决。下面,我们将介绍python中四种二叉搜索树的实现。

1. Python实现简单二叉搜索树

在BST的实现中,节点对象包含“val“、”left”和”right”三个域,其中”val“表示节点的值,”left”和”right”分别指向左右子树。get()方法用来查找值,insert()方法用来插入新节点。

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

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

    def get(self, val):
        if self.root is None:
            return None
        else:
            return self._get(val, self.root)

    def _get(self, val, cur_node):
        if cur_node.val == val:
            return cur_node
        elif val < cur_node.val and cur_node.left is not None:
            return self._get(val, cur_node.left)
        elif val > cur_node.val and cur_node.right is not None:
            return self._get(val, cur_node.right)
        else:
            return None

    def insert(self, val):
        if self.root is None:
            self.root = Node(val)
        else:
            self._insert(val, self.root)

    def _insert(self, val, cur_node):
        if val < cur_node.val:
            if cur_node.left is None:
                cur_node.left = Node(val)
            else:
                self._insert(val, cur_node.left)
        elif val > cur_node.val:
            if cur_node.right is None:
                cur_node.right = Node(val)
            else:
                self._insert(val, cur_node.right)
        else:
            print('Value already in tree.')

下面给出一个简单例子,创建一棵二叉搜索树并插入一些新值:

tree = BinarySearchTree()
tree.insert(6)
tree.insert(3)
tree.insert(9)
tree.insert(2)
tree.insert(4)
tree.insert(8)
tree.insert(10)

2. Python实现AVL树

AVL树是一种自平衡的二叉搜索树,在应用于高并发、高IO、高负载的情况下可以减少树的深度,从而提升搜索的效率。与简单二叉搜索树不同,AVL树可以旋转来自平衡,保证在对一组n个数据进行建树之后的深度总是O(logn)。

class Node:
    def __init__(self, val):
        self.left = None
        self.right = None
        self.val = val
        self.height = 1

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

    def _get_height(self, node):
        if not node:
            return 0
        return node.height

    def _get_balance(self, node):
        if not node:
            return 0
        return self._get_height(node.left) - self._get_height(node.right)

    def _fix_height(self, node):
        node.height = 1 + max(self._get_height(node.left),
                              self._get_height(node.right))

    def _right_rotate(self, y):
        x = y.left
        T2 = x.right

        x.right = y
        y.left = T2

        self._fix_height(y)
        self._fix_height(x)

        return x

    def _left_rotate(self, x):
        y = x.right
        T2 = y.left

        y.left = x
        x.right = T2

        self._fix_height(x)
        self._fix_height(y)

        return y

    def insert(self, val):
        def _insert(node, val):
            if not node:
                return Node(val)
            elif val < node.val:
                node.left = _insert(node.left, val)
            elif val > node.val:
                node.right = _insert(node.right, val)
            else:
                return node

            self._fix_height(node)

            balance = self._get_balance(node)

            if balance > 1 and val < node.left.val:
                return self._right_rotate(node)

            if balance < -1 and val > node.right.val:
                return self._left_rotate(node)

            if balance > 1 and val > node.left.val:
                node.left = self._left_rotate(node.left)
                return self._right_rotate(node)

            if balance < -1 and val < node.right.val:
                node.right = self._right_rotate(node.right)
                return self._left_rotate(node)

            return node

        self.root = _insert(self.root, val)

下面给出一个简单例子,创建一棵AVL树并插入一些新值:

tree = AVLTree()

tree.insert(9)
tree.insert(5)
tree.insert(10)
tree.insert(0)
tree.insert(6)
tree.insert(11)
tree.insert(-1)
tree.insert(1)
tree.insert(2)

3. Python实现红黑树

红黑树也是自平衡的二叉搜索树。它通过颜色标记节点来保证在一组n个数据中经过建树之后深度总是O(logn)。

RED = True
BLACK = False

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

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

    @staticmethod
    def _color(node):
        if node is None:
            return BLACK
        else:
            return node.color

    def _rotate_left(self,node):
        right_node=node.right
        node.right= right_node.left
        right_node.left= node
        right_node.color= node.color
        node.color= RED
        return right_node

    def _rotate_right(self,node):
        left_node= node.left
        node.left= left_node.right
        left_node.right= node
        left_node.color= node.color
        node.color= RED
        return left_node

    def _flip_color(self,node):
        node.color= RED
        node.left.color= BLACK
        node.right.color= BLACK

    def insert(self, val):

        def _insert(node, val):
            if not node:
                return Node(val, RED)

            if val < node.val:
                node.left = _insert(node.left, val)
            elif val > node.val:
                node.right = _insert(node.right, val)

            if self._color(node.right) == RED and self._color(node.left) == BLACK:
                node = self._rotate_left(node)

            if self._color(node.left) == RED and self._color(node.left.left) == RED:
                node = self._rotate_right(node)

            if self._color(node.left) == RED and self._color(node.right) == RED:
                self._flip_color(node)

            return node

        self.root = _insert(self.root, val)
        self.root.color = BLACK

下面给出一个简单例子,创建一棵红黑树并插入一些新值:

tree = RedBlackTree()

tree.insert(9)
tree.insert(5)
tree.insert(10)
tree.insert(0)
tree.insert(6)
tree.insert(11)
tree.insert(-1)
tree.insert(1)
tree.insert(2)

4. Python实现B树

B树是一种多路平衡查找树,本质上是一个多叉排序树,可以用来解决大数据量的存储和索引问题。B树的特点是每个节点可以有多个儿子,如2-3树一样保持平衡,既能够保证查询效率,又能够提供插入和删除的功能。

class Node:
    def __init__(self, t, leaf=False):
        self.t = t
        self.keys = []
        self.children = []
        self.leaf = leaf

    def split(self, parent, i):
        t = self.t
        new_node = Node(t, leaf=self.leaf)
        parent.children.insert(i + 1, new_node)
        parent.keys.insert(i, self.keys[t - 1])
        new_node.children = self.children[t:]
        self.children = self.children[:t - 1]
        new_node.keys = self.keys[t:]
        self.keys = self.keys[:t - 1]
        return parent

    def insert(self, k):
        i = len(self.keys) - 1
        if self.leaf:
            self.keys.append(None)
            while i >= 0 and k < self.keys[i]:
                self.keys[i + 1] = self.keys[i]
                i -= 1
            self.keys[i + 1] = k
            return self, None
        else:
            while i >= 0 and k < self.keys[i]:
                i -= 1
            i += 1
            if len(self.children[i].keys) == 2 * self.t - 1:
                return self.children[i].insert(k).split(self, i)
            else:
                return self.children[i].insert(k), None

class BTree:
    def __init__(self, t=2):
        self.t = t
        self.root = Node(t, leaf=True)

    def search(self, k):
        x = self.root
        while x is not None:
            i = 0
            while i < len(x.keys) and k > x.keys[i]:
                i += 1
            if i < len(x.keys) and k == x.keys[i]:
                return x
            if x.leaf:
                return None
            else:
                x = x.children[i]
        return None

    def insert(self, k):
        node, split = self.root.insert(k)
        if split is not None:
            self.root = Node(self.t, leaf=False)
            self.root.children = [node, split]
            self.root.keys = [split.keys[0]]

下面给出一个简单例子,创建一棵B树并插入一些新值:

tree = BTree(2)

for i in range(1, 11):
    tree.insert(i)

search_val = 8

if tree.search(search_val):
    print("{} is found in the B-tree".format(search_val))
else:
    print("{} is not found in the B-tree".format(search_val))

# Output: 8 is found in the B-tree

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:python 实现二叉搜索树的四种方法 - Python技术站

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

相关文章

  • 详解利用上下文管理器扩展Python计时器

    标题:详解利用上下文管理器扩展Python计时器 1. 引言 在程序编写和调试过程中,经常需要对程序某个部分的运行时间进行计时,以便找出程序的性能瓶颈并加以优化。Python 提供了 time 模块用于处理时间相关操作,其中 time.time() 函数可以获取当前时间戳。在使用计时器的时候,我们可以通过记录程序开始和结束时的时间戳之差来计算程序的运行时间。…

    python 2023年6月2日
    00
  • python3:excel操作之读取数据并返回字典 + 写入的案例

    下面是关于“python3:excel操作之读取数据并返回字典+写入的案例”的完整攻略。 简介 本次教程将介绍如何使用Python3操作Excel文件。我们将会学习如何读取Excel文件中的数据,并将其转化为python字典格式;以及如何将Python数据写入到Excel文件中。我们将使用Python标准库中的openpyxl工具。 准备工作 在开始之前,我…

    python 2023年5月13日
    00
  • Python 序列化反序列化和异常处理的问题小结

    Python序列化反序列化和异常处理是 Python 编程中非常重要的话题。序列化是指把内存中的数据按一定的格式保存到硬盘或者传输,反序列化则是指从硬盘或者网络加载相应的数据并重新构造到内存中。异常处理则是指针对可能出现的各种意外情况进行预先的处理,从而使程序能够更加健壮的运行。 一、Python 序列化和反序列化 Python 中常见的序列化和反序列化格式…

    python 2023年5月13日
    00
  • Python ARP扫描与欺骗实现全程详解

    Python ARP扫描与欺骗实现全程详解 概述 ARP(Address Resolution Protocol)地址解析协议是TCP/IP协议族下运用链路层的一个通讯协议,主要用于解析目标设备的硬件地址(MAC地址)与网络地址(IP地址)的对应关系,实现数据包在局域网上的发送与接收。 本文将详细讲解如何使用Python实现ARP扫描,发现局域网中的设备,以…

    python 2023年6月3日
    00
  • 名称“endCol”未在 python 脚本中定义

    【问题标题】:name ‘endCol’ is not defined in python script名称“endCol”未在 python 脚本中定义 【发布时间】:2023-04-03 13:45:01 【问题描述】: 我不知道为什么我的变量没有定义 我的代码: def menu(): print(“Please select the followin…

    Python开发 2023年4月8日
    00
  • python迭代器实例简析

    Python迭代器实例简析 迭代器是什么 在Python中,迭代器是一个访问集合的对象,它通过 next() 方法实现了对元素的逐个访问,当所有元素被访问完毕后,会抛出 StopIteration 异常。 迭代器的优点 与Python中常用的序列(list, tuple, string等)相比,迭代器具有如下优点: 不要求在内存中创建完整的数据结构,节省内存…

    python 2023年6月6日
    00
  • 浅谈Python2.6和Python3.0中八进制数字表示的区别

    浅谈Python2.6和Python3.0中八进制数字表示的区别 在Python中,数字可以用十进制、八进制和十六进制来表示,本文主要讨论Python2.6和Python3.0中八进制数字表示的区别。 Python2.6中的八进制数字表示 在Python2.6及之前的版本中,八进制数字可以用0开头表示,如下所示: >>> octal_num…

    python 2023年6月3日
    00
  • Python collections.defaultdict模块用法详解

    Python collections.defaultdict模块用法详解 概述 Python中的collections模块提供了一种名为defaultdict的数据类型,它是一个子类(dict class)。 这意味着defaultdict类继承了dict类中所有的方法,而且还有自己的实现。在使用defaultdict时,如果字典中的键不存在,它可以自动创建…

    python 2023年6月3日
    00
合作推广
合作推广
分享本页
返回顶部