广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Python利用treap实现双索引的方法
  • 555
分享到

Python利用treap实现双索引的方法

2024-04-02 19:04:59 555人浏览 薄情痞子

Python 官方文档:入门教程 => 点击学习

摘要

前言: 在很多应用场景下,我们不但需要堆的特性,例如快速知道数据最大值或最小值,同时还需要知道元素的排序信息,因此本节我们看看如何实现鱼和熊掌如何兼得。假设我们有一系列数据,它的元

前言:

在很多应用场景下,我们不但需要堆的特性,例如快速知道数据最大值或最小值,同时还需要知道元素的排序信息,因此本节我们看看如何实现鱼和熊掌如何兼得。假设我们有一系列数据,它的元素由两部分组成,一部分对应商品的名称,其类型为字符串,一部分对应商品的货存数量,类型为整形,我们既需要将商品根据其名称排序,同时我们又需要快速查询当前货存最小的商品,我们如何设计相应的算法数据结构来满足这样特性呢。

举个例子,如下图:

从上图看,它对应元素字符串是排序二叉树,因此根节点左子树对应元素的字符串都小于根字符串,同时右子树对应的字符串都大于根节点字符串,同时每个元素还对应着相应商品的货存数量,我们需要及时掌握当前货存最少的商品,这样才能在其耗尽之前迅速补货。但是从上图可以看到,要保证字符串的排序性就得牺牲对于商品数量的小堆性质,例如上图中water对应的货存与wine对应的货存违背了小堆的性质,现在问题是如何在保证字符串排序的情况下,确保数量同时能满足小堆性质。

首先我们先定义一下数据结构:


class node: 
    def __init__(self, key: str, priority: float): 
        self._key = key 
        self._priority = priority 
        self._left: Node = None 
        self._right: Node = None 
        self._parent: Node = None 
 
    @property 
    def left(self): 
        return self._left 
 
    @property 
    def right(self): 
        return self._right 
 
    @property 
    def parent(self): 
        return self._parent 
 
    @left.setter 
    def left(self, node): 
        self._left = node 
        if node is not None: 
            node.parent = self 
 
    @right.setter 
    def right(self, node): 
        self._right = node 
        if node is not None: 
            node.parent = self 
 
    @parent.setter 
    def parent(self, node): 
        self._parent = node 
 
    def is_root(self) -> bool: 
        if self.parent is None: 
            return True 
        return False 
 
    def __repr__(self): 
        return "({}, {})".fORMat(self._key, self._priority) 
 
    def __str__(self): 
        repr_str: str = "" 
        repr_str += repr(self) 
        if self.parent is not None: 
            repr_str += " parent: " + repr(self.parent) 
        else: 
            repr_str += " parent: None" 
 
        if self.left is not None: 
            repr_str += " left: " + repr(self.left) 
        else: 
            repr_str += " left: None" 
 
        if self.right is not None: 
            repr_str += " right: " + repr(self.right) 
        else: 
            repr_str += " right: None" 
 
        return repr_str 
 
class Treap: 
    def  __init__(self): 
        self.root : Node = None 

当前问题是,当上图所示的矛盾出现时,我们如何调整,使得字符串依然保持排序性质,同时货存数值能满足小堆性质。我们需要根据几种情况采取不同操作,首先看第一种,如下图:

从上图看到,一种情况是父节点与左孩子在数值上违背了堆的性质,此时我们执行一种叫右旋转操作,

其步骤是:

  1. Beer节点逆时针旋转,替换其父节点;
  2. 父节点Cabbage顺时针旋转,成为Beer的右孩子节点;
  3. 原来Beer的右孩子节点转变为Cabbage的左孩子节点;

完成后结果如下图所示:

可以看到,此时字符串依然保持排序二叉树性质,同时数值对应的小堆性质也得到了满足。

我们看看代码实现:


class Treap: 
    def __init__(self): 
        self._root: Node = None 
 
    def right_rotate(self, x: Node): 
        if x is None or x.is_root() is True: 
            return 
 
        y = x.parent 
        if y.left != x:  # 必须是左孩子才能右旋转 
            return 
 
        p = y.parent 
        if p is not None:  # 执行右旋转 
            if p.left == y: 
                p.left = x 
            else: 
                p.right = x 
        else: 
            self._root = x 
 
        y.left = x.right 
        x.right = y 


接下来我们构造一些数据测试一下上面的实现是否正确:


def setup_right_rotate(): 
    flour: Node = Node("Flour", 10) 
    cabbage: Node = Node("Cabbage", 77) 
    beer: Node = Node("Beer", 76) 
    bacon: Node = Node("Bacon", 95) 
    butter: Node = Node("Butter", 86) 
 
    flour.parent = None 
    flour.left = cabbage 
    flour.right = None 
    cabbage.left = beer 
 
 
    beer.left = bacon 
    beer.right = butter 
 
    return flour, beer 
 
def print_treap(n: Node): 
    if n is None: 
        return 
 
    print(n) 
    print_treap(n.left) 
    print_treap(n.right) 
 
treap = Treap() 
root, x , cabbage = setup_right_rotate() 
print("---------before right rotate---------:") 
print_treap(root) 
treap.right_rotate(x) 
print("-------after right rotate-------") 
print_treap(root) 


上面代码执行后输出内容如下:

---------before right rotate---------:
(Flour, 10) parent: None left: (Cabbage, 77) right: None
(Cabbage, 77) parent: (Flour, 10) left: (Beer, 76) right: (Eggs, 129)
(Beer, 76) parent: (Cabbage, 77) left: (Bacon, 95) right: (Butter, 86)
(Bacon, 95) parent: (Beer, 76) left: None right: None
(Butter, 86) parent: (Beer, 76) left: None right: None
(Eggs, 129) parent: (Cabbage, 77) left: None right: None
-------after right rotate-------
(Flour, 10) parent: None left: (Beer, 76) right: None
(Beer, 76) parent: (Flour, 10) left: (Bacon, 95) right: (Cabbage, 77)
(Bacon, 95) parent: (Beer, 76) left: None right: None
(Cabbage, 77) parent: (Beer, 76) left: (Butter, 86) right: (Eggs, 129)
(Butter, 86) parent: (Cabbage, 77) left: None right: None
(Eggs, 129) parent: (Cabbage, 77) left: None right: None

对比右旋转前后输出的二叉树看,旋转后的二叉树打印信息的确跟上面我们旋转后对应的图像是一致的。接下来我们实现左旋转,先把上图中cabbage节点对应的值改成75,这样它与父节点就违背了小堆性质:

 

我们要做的是:

  1. cabbage节点向“左”旋转到beer的位置;
  2. beer的父节点设置为cabbage;
  3. beer的右孩子设置为cabbage的左孩子;
  4. cabbage的左孩子变成beer;左旋转后二叉树

成形如下:

 

从上图看,左旋转后,字符串依然保持二叉树排序性,同时数值的排放也遵守小堆原则,我们看相应的代码实现:


class Treap: 
   ... 
 
    def left_rotate(self, x : Node): 
        if x is None or x.is_root() is True: 
            return 
 
        y = x.parent 
        if y.right is not x: # 只有右孩子才能左旋转 
            return 
 
        p = y.parent 
        if p is not None: 
            if p.left is y: 
                p.left = x 
            else: 
                p.right = x 
        else: 
            self._root = x 
 
        y.right = x.left 
        x.left = y 


为了测试上面代码实现,我们首先把cabbage的值修改,然后调用上面代码:


cabbage._priority = 75 
print("-------before left rotate--------") 
print_treap(root) 
treap.left_rotate(cabbage) 
print("-------after left rotate---------") 
print_treap(root) 


代码运行后输出结果为:

-------before left rotate--------
(Flour, 10) parent: None left: (Beer, 76) right: None
(Beer, 76) parent: (Flour, 10) left: (Bacon, 95) right: (Cabbage, 75)
(Bacon, 95) parent: (Beer, 76) left: None right: None
(Cabbage, 75) parent: (Beer, 76) left: (Butter, 86) right: (Eggs, 129)
(Butter, 86) parent: (Cabbage, 75) left: None right: None
(Eggs, 129) parent: (Cabbage, 75) left: None right: None
-------after left rotate---------
(Flour, 10) parent: None left: (Cabbage, 75) right: None
(Cabbage, 75) parent: (Flour, 10) left: (Beer, 76) right: (Eggs, 129)
(Beer, 76) parent: (Cabbage, 75) left: (Bacon, 95) right: (Butter, 86)
(Bacon, 95) parent: (Beer, 76) left: None right: None
(Butter, 86) parent: (Beer, 76) left: None right: None
(Eggs, 129) parent: (Cabbage, 75) left: None right: None

输出结果的描述与上图左旋转后的结果是一致的。由于Treap相对于元素的key是排序二叉树,因此在给定一个字符串后,我们很容易查询字符串是否在Treap中,其本质就是排序二叉树的搜索,其实现我们暂时忽略。

虽然查询很简单,但是插入节点则稍微麻烦,因为插入后,新节点与其父节点可能会违背小堆性质,因此在完成插入后,我们还需使用上面实现的左旋转或右旋转来进行调整。

到此这篇关于python使用treap实现双索引的方法的文章就介绍到这了,更多相关Python使用treap实现双索引内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: Python利用treap实现双索引的方法

本文链接: https://www.lsjlt.com/news/135583.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Python利用treap实现双索引的方法
    前言: 在很多应用场景下,我们不但需要堆的特性,例如快速知道数据最大值或最小值,同时还需要知道元素的排序信息,因此本节我们看看如何实现鱼和熊掌如何兼得。假设我们有一系列数据,它的元...
    99+
    2022-11-12
  • mysql索引的实现方法
    mysql索引的实现方法?这个问题可能是我们日常学习或工作经常见到的。希望通过这个问题能让你收获颇深。下面是小编给大家带来的参考内容,让我们一起来看看吧!MySQL索引的概念索引是一种特殊的文件(InnoD...
    99+
    2022-10-18
  • Python搜索引擎实现原理和方法
    如何在庞大的数据中高效的检索自己需要的东西?本篇内容介绍了Python做出一个大数据搜索引擎的原理和方法,以及中间进行数据分析的原理也给大家做了详细介绍。 布隆过滤器 (Bloom Filter) 第一步我...
    99+
    2022-06-04
    原理 搜索引擎 方法
  • C#转义字符双引号的实现方法
    这篇文章主要讲解了“C#转义字符双引号的实现方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C#转义字符双引号的实现方法”吧!转义字符 \◆一种特殊的字符常量;◆以反斜线"\&q...
    99+
    2023-06-17
  • 如何利用Python实现高效索引大数据?
    Python作为一种强大的编程语言,已经成为了数据分析和处理领域中的不可或缺的工具。对于大数据的处理和分析,Python也提供了很多强大的工具和库。本文将介绍如何利用Python实现高效索引大数据。 一、什么是数据索引? 在处理大数据时,...
    99+
    2023-08-04
    索引 异步编程 大数据
  • NumPy索引的PHP打包实现方法?
    对于数据科学和计算机编程的爱好者而言,NumPy是一个非常重要的Python库,可以用于处理和操作大型数组和矩阵。然而,有时候我们需要在其他编程语言中使用NumPy的功能。在这篇文章中,我们将讨论如何使用PHP中的打包功能实现NumPy的索...
    99+
    2023-09-04
    打包 numpy 索引
  • Python二叉搜索树与双向链表转换实现方法
    本文实例讲述了Python二叉搜索树与双向链表实现方法。分享给大家供大家参考,具体如下: # encoding=utf8 ''' 题目:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。 要求...
    99+
    2022-06-04
    双向 链表 方法
  • 使用高斯Redis实现二级索引的方法
    目录一、背景二、场景一:词典补全2.1 基本方案2.2 与频率相关的词典补全三、场景二:多维索引3.1 数据编码3.2 添加新元素3.3 查询四、总结一、背景 提起索引,第一印象就是数据库的名词,但是,高斯Redis也可...
    99+
    2022-07-08
    Redis二级索引 Redis二级索引使用 高斯Redis索引
  • Python re.sub反向引用的实现方法
    这篇文章主要讲解了“Python re.sub反向引用的实现方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python re.sub反向引用的实现方法”吧!目录match 分组re.su...
    99+
    2023-06-20
  • Node与Python双向通信的实现方法
    这篇文章主要介绍“Node与Python双向通信的实现方法”,在日常操作中,相信很多人在Node与Python双向通信的实现方法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Node与Python双向通信的实...
    99+
    2023-06-20
  • Python实现仿真双径效应的方法
    多径效应 多径效应(multipath effect):指电磁波经不同路径传播后,各分量场到达接收端时间不同,按各自相位相互叠加而造成干扰,使得原来的信号失真,或者产生错误。比如电磁波沿不同的两条路径传播,而两条路径...
    99+
    2022-06-02
    Python 仿真双径效应
  • MySQL8中降序索引底层的实现方法
    这篇文章主要讲解了MySQL8中降序索引底层的实现方法,内容清晰明了,对此有兴趣的小伙伴可以学习一下,相信大家阅读完之后会有帮助。什么是降序索引大家可能对索引比较熟悉,而对降序索引比较陌生,事实上降序索引是...
    99+
    2022-10-18
  • Java中的排序数索引怎么利用分治算法实现
    Java中的排序数索引怎么利用分治算法实现?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。具体如下:public class Ono { public static i...
    99+
    2023-05-31
    java 索引 分治算法
  • Python实现Sqlite将字段当做索引进行查询的方法
    本文实例讲述了Python实现Sqlite将字段当做索引进行查询的方法。分享给大家供大家参考,具体如下: 默认从sqlite中获取到的数据是数字索引的, 在开发阶段经常有修改数据库所以显得不太方便, 其实在...
    99+
    2022-06-04
    字段 索引 方法
  • MySQL利用索引优化ORDER BY排序语句的方法
    创建表&创建索引 create table tbl1 ( id int unique, sname varchar(50), index tbl1_index_sname(sname desc)...
    99+
    2022-05-24
    MySQL 优化ORDER BY语句 MySQL 优化排序语句 MySQL 索引优化
  • LRUCache的实现原理及利用python实现的方法
    简介 LRU(Least Recently Used)最近最少使用,最近有时间和空间最近的歧义,所以我更喜欢叫它近期最少使用算法。它的核心思想是,如果一个数据被访问过,我们有理由相信它在将来被访问的概率就越...
    99+
    2022-06-04
    原理 方法 LRUCache
  • 利用Python实现定时程序的方法
    目录定时器概念实现一个简单的定时程序方案一方案二定时器概念 什么是定时器呢?它是指从指定的时刻开始,经过一个指定时间,然后触发一个事件,用户可以自定义定时器的周期与频率。 实现一个简单的定时程序 方案一 在 ...
    99+
    2022-06-02
    Python 定时程序 Python 定时
  • 利用Python实现数值积分的方法
    目录1. 栗子2. 矩形计算面积2.1 左侧边长计算面积2.2 右侧边长计算面积2.3 中值边长计算面积3. 梯形计算面积4. 真值比对5. 总结1. 栗子 为了加深大家的印象,首先...
    99+
    2022-11-13
  • 怎么使用Python中Pandas的索引对齐方法
    本篇内容介绍了“怎么使用Python中Pandas的索引对齐方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!一.索引对象支持集合运算:联合...
    99+
    2023-06-02
  • Java编程实战:如何利用数组索引实现高效算法?
    在Java编程中,数组是一种基础数据结构,它可以存储一组相同类型的数据。在算法设计中,数组索引是一种重要的工具,它可以帮助我们快速地访问数组中的元素。本文将介绍如何利用数组索引实现高效算法。 一、数组索引的基础知识 在Java中,数组索引...
    99+
    2023-11-12
    索引 数组 编程算法
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作