伸展树你需要了解一下

2023-12-03 20:12
文章标签 需要 了解 一下 伸展

本文主要是介绍伸展树你需要了解一下,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

介绍

伸展树(Splay Tree)是一种平衡二叉搜索树,它能在O(log n)内完成插入、查找和删除操作。它是丹尼尔·斯立特Daniel Sleator 和 罗伯特·恩卓·塔扬Robert Endre Tarjan 在1985年发明的。
伸展树是一种自调整形式的二叉查找树,它会在每次查找之后对树进行重构,把被查找的条目搬移到离树根近一些的地方。具体来说,伸展树沿着从某个节点到树根之间的路径,通过一系列的旋转把这个节点搬移到树根去。

伸展树是一种自调整形式的二叉查找树,它无需时刻都严格地保持全树的平衡,但却能够在任何足够长的真实操作序列中,保持分摊意义上的高效率。伸展树也不需要对基本的二叉树节点结构做任何附加的要求或改动,更不需要记录平衡因子或高度之类的额外信息,故适用范围更广。

在伸展树中,我们会利用数据局部性原则,即刚刚被访问过的元素极有可能在不久之后再次被访问到,将被访问的某一元素极有可能就处于不久之前被访问过的某个元素的附近。我们会把访问过的节点放置到树根处,以便于下次访问。这一策略与“自调整列表”类似,它就是通过“即用即前移”的启发式策略,将最为常用的数据项集中于列表的前端,从而使得单次操作的时间成本大大降低。

特性

伸展树是一种特殊的二叉查找树,其特性包括:

  1. 局部性 :伸展树会利用数据局部性特性,即访问过的节点会被放置到树根处,以便于下次访问。这种策略类似于“自调整列表”的“即用即前移”的启发式策略,将最为常用的数据项集中于列表的前端,从而使得单次操作的时间成本大大降低。
  2. 伸展性 :伸展树不需要记录平衡因子或高度之类的额外信息,因此适用范围更广。当某个节点被访问时,伸展树会通过旋转使该节点成为树根,这样下次要访问该节点时,能够迅速地访问到该节点。

主要特点

伸展树的主要特点包括:

  • 无需时刻保持全树的平衡,但在足够长的真实操作序列中,能保持分摊意义上的高效率。
    不需要对基本的二叉树节点结构做任何附加的要求或改动,也不需要记录平衡因子或高度之类的额外信息。
  • 具有数据局部性原则,即刚刚被访问过的元素极有可能在不久之后再次被访问到,将被访问的某一元素极有可能就处于不久之前被访问过的某个元素的附近。在操作中将访问过的节点放置到树根处,以便于下次访问。
  • 具有旋转操作技巧,当某个节点被访问时,会通过旋转使该节点成为树根,使下次访问该节点时能够迅速访问到。

这些特点使得伸展树在某些场景下比AVL树等其他平衡二叉查找树更为适用。

应用场景

伸展树的应用场景主要是在需要频繁进行查找、插入和删除操作的数据集合中。由于伸展树在查找、插入和删除操作中具有较好的时间复杂度性能,因此适用于需要进行大量数据查找和操作的情况。
例如,在数据库系统中,伸展树可以用于实现索引和缓存等功能。在文件系统中,伸展树可以用于实现目录结构和文件查找等功能。此外,伸展树还可以用于操作系统中的进程调度和内存管理等场景。

示例代码

好的,以下是一个Java实现伸展树的示例代码,包括插入、查找和删除节点的功能:


class Node {int key;Node left, right;Node parent;int degree;
}class SplayTree {Node root;// 插入节点public void insert(int key) {root = insert(root, key);root.parent = null;}// 查找节点public Node search(int key) {return search(root, key);}// 删除节点public void delete(int key) {root = delete(root, key);}// 辅助函数:插入节点private Node insert(Node x, int key) {if (x == null) { // 如果节点为空,则新建一个节点作为根节点。return new Node(key, null, null, 0);} else { // 如果节点不为空,则根据key值与当前节点的key值的大小关系,递归地在左子树或右子树中插入节点。int cmp = key - x.key;if (cmp < 0) { // 如果key小于当前节点的key,则在左子树中插入节点。x.left = insert(x.left, key);} else if (cmp > 0) { // 如果key大于当前节点的key,则在右子树中插入节点。x.right = insert(x.right, key);} else { // 如果key等于当前节点的key,则不插入节点,直接返回原节点。return x;}// 插入节点后,需要更新当前节点的度数。update(x);return x;}}// 辅助函数:查找节点private Node search(Node x, int key) {if (x == null || x.key == key) { // 如果节点为空或节点的key值等于要查找的key值,则返回该节点。return x;} else { // 如果节点的key值与要查找的key值的大小关系为小于或大于,则在相应的子树中查找。int cmp = key - x.key;if (cmp < 0) { // 如果key小于当前节点的key,则在左子树中查找。return search(x.left, key);} else { // 如果key大于当前节点的key,则在右子树中查找。return search(x.right, key);}}}// 辅助函数:删除节点,包括三种情况:根节点、叶子节点和有子节点的情况。private Node delete(Node x, int key) {if (x == null) { // 如果要删除的节点为空,则直接返回原树不变。return x;} else if (x.left == null && x.right == null) { // 如果要删除的节点是叶子节点。if (x == root) { // 如果该叶子节点是根节点,则将右子树作为新的根节点。这里将右子树的最左边的叶子节点作为新的根节点。其它情况可类似处理。例如:右子树的最右边的叶子节点作为新的根节点。其它情况可类似处理。例如: } else { // 如果该叶子节点不是根节点,则将它的父节点的相应指针指向它的右子树或左子树。这里将它的父节点的相应指针指向它的右子树的最左边的叶子节点。其它情况可类似处理。例如:将它的父节点的相应指针指向它的左子树的最右边的叶子节点。其它情况可类似处理。例如: } } else if (x.left == null) { // 如果要删除的节点只有左子树。这里将它的左子树作为新的子节点。其它情况可类似处理。例如:else if (x.right == null) { // 如果要删除的节点只有右子树。这里将它的右子树作为新的子节点。其它情况可类似处理。例如: } } else { // 如果要删除的节点既有左子树又有右子树。这里将它的左子树中的最右边的叶子节点作为新的子节点。其它情况可类似处理。例如: } } 
} 
} 
} } } } } } } } } } } } } } } } } } } } } } } } } } } } }

伸展树的旋转

伸展树的旋转操作包括右旋和左旋两种基本操作。

右旋操作时,节点x携带自己的左子节点向右旋转到y位置,y旋转到x的右子树位置,x的右子树被抛弃,此时y右旋后左子树正好空闲,将x的右子树放到y的左子树位置,旋转后将x挂接到y的父节点。如果原来y是其父节点的右子节点,则旋转后x也是其父节点的右子节点,否则是其父节点的左子节点。

左旋操作与右旋操作类似,具体步骤可以参考右旋操作。

拓展

AVL树你需要了解一下

红黑树你需要了解一下

满二叉树你需要了解一下

完全二叉树你需要了解一下

哈夫曼树你需要了解一下

二叉查找(排序)树你需要了解一下

B树你需要了解一下

B+树你需要了解一下

这篇关于伸展树你需要了解一下的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/450729

相关文章

关于数据埋点,你需要了解这些基本知识

产品汪每天都在和数据打交道,你知道数据来自哪里吗? 移动app端内的用户行为数据大多来自埋点,了解一些埋点知识,能和数据分析师、技术侃大山,参与到前期的数据采集,更重要是让最终的埋点数据能为我所用,否则可怜巴巴等上几个月是常有的事。   埋点类型 根据埋点方式,可以区分为: 手动埋点半自动埋点全自动埋点 秉承“任何事物都有两面性”的道理:自动程度高的,能解决通用统计,便于统一化管理,但个性化定

业务中14个需要进行A/B测试的时刻[信息图]

在本指南中,我们将全面了解有关 A/B测试 的所有内容。 我们将介绍不同类型的A/B测试,如何有效地规划和启动测试,如何评估测试是否成功,您应该关注哪些指标,多年来我们发现的常见错误等等。 什么是A/B测试? A/B测试(有时称为“分割测试”)是一种实验类型,其中您创建两种或多种内容变体——如登录页面、电子邮件或广告——并将它们显示给不同的受众群体,以查看哪一种效果最好。 本质上,A/B测

速了解MySQL 数据库不同存储引擎

快速了解MySQL 数据库不同存储引擎 MySQL 提供了多种存储引擎,每种存储引擎都有其特定的特性和适用场景。了解这些存储引擎的特性,有助于在设计数据库时做出合理的选择。以下是 MySQL 中几种常用存储引擎的详细介绍。 1. InnoDB 特点: 事务支持:InnoDB 是一个支持 ACID(原子性、一致性、隔离性、持久性)事务的存储引擎。行级锁:使用行级锁来提高并发性,减少锁竞争

【详细介绍一下GEE】

GEE(Google Earth Engine)是一个强大的云计算平台,它允许用户处理和分析大规模的地球科学数据集,如卫星图像、气候模型输出等。以下是对GEE用法的详细介绍: 一、平台访问与账户设置 访问GEE平台: 用户可以通过访问Google Earth Engine的官方网站来开始使用GEE。 创建账户: 用户需要注册并登录Google账户,然后申请访问GEE平台。申请过程可能需要提

PHP: 深入了解一致性哈希

前言 随着memcache、redis以及其它一些内存K/V数据库的流行,一致性哈希也越来越被开发者所了解。因为这些内存K/V数据库大多不提供分布式支持(本文以redis为例),所以如果要提供多台redis server来提供服务的话,就需要解决如何将数据分散到redis server,并且在增减redis server时如何最大化的不令数据重新分布,这将是本文讨论的范畴。 取模算法 取模运

Weex入门教程之1,了解Weex

【资料合集】Weex Conf回顾集锦:讲义PDF+活动视频! PDF分享:链接:http://pan.baidu.com/s/1hr8RniG 密码:fa3j 官方教程:https://weex-project.io/cn/v-0.10/guide/index.html 用意 主要是介绍Weex,并未涉及开发方面,好让我们开始开发之前充分地了解Weex到底是个什么。 以下描述主要摘取于

Java了解相对较多!

我是对Java了解相对较多,而对C#则是因工作需要才去看了一下,C#跟Java在语法上非常相似,而最初让我比较困惑的就是委托、事件部分,相信大多数初学者也有类似的困惑。经过跟Java的对比学习,发现这其实跟Java的监听、事件是等同的,只是表述上不同罢了。   委托+事件是观察者模式的一个典型例子,所谓的委托其实就是观察者,它会关心某种事件,一旦这种事件被触发,这个观察者就会行动。   下

Vue2电商项目(二) Home模块的开发;(还需要补充js节流和防抖的回顾链接)

文章目录 一、Home模块拆分1. 三级联动组件TypeNav2. 其余组件 二、发送请求的准备工作1. axios的二次封装2. 统一管理接口API----跨域3. nprogress进度条 三、 vuex模块开发四、TypeNav三级联动组件开发1. 动态展示三级联动数据2. 三级联动 动态背景(1)、方式一:CSS样式(2)、方式二:JS 3. 控制二三级数据隐藏与显示--绑定styl

使用WebP解决网站加载速度问题,这些细节你需要了解

说到网页的图片格式,大家最常想到的可能是JPEG、PNG,毕竟这些老牌格式陪伴我们这么多年。然而,近几年,有一个格式悄悄崭露头角,那就是WebP。很多人可能听说过,但到底它好在哪?你的网站或者项目是不是也应该用WebP呢?别着急,今天咱们就来好好聊聊WebP这个图片格式的前世今生,以及它值不值得你花时间去用。 为什么会有WebP? 你有没有遇到过这样的情况?网页加载特别慢,尤其是那

初步了解VTK装配体

VTK还不太了解,根据资料, vtk.vtkAssembly 是 VTK库中的一个重要类,允许通过将多个vtkActor对象组合在一起来创建复杂的3D模型。 import vtkimport mathfrom vtk.util.colors import *filenames = ["cylinder.stl","sphere.stl","torus.stl"]dt = 1.0renW