左偏树leftistTree和斜堆skewHeap的分析和实现

左偏树原理详解 算法和数据结构 阅读详情

最近学习了很多东西(深入学习操作系统中), 博客的更新也搁置了一段时间, 主要是学习占用了大量的时间 (学的越多, 也发现自己不会的越多, 就像苏格拉底说的"我只知道我一无所知");

今天主要分析一下左偏树和斜堆, 这两个数据结构是二叉堆的进化版, 一方面能够实现与二叉堆相同的功能, 代码结构也比较简单; 另一方面它们的合并操作的时间复杂度为O(logn), 而普通二叉堆实现合并操作的时间复杂度为O(n);

左偏树的性质:

--本节点的键值key小于其左右子节点键值key(与二叉堆相同);

--本节点的左子节点的距离大于等于本节点的右子节点(这意味着每个节点中除了要存储键值外, 还需要一个额外的dist存储距离);

--节点的距离是其右子节点的距离+1(这意味着, 一个节点的dist是从它出发到达最近终端节点的距离);

斜堆的性质:

--本节点的键值key小于其左右子节点键值key;

--斜堆节点不存储距离dist值, 取而代之的是在每次合并操作时都做swap处理(节省了存储空间);


核心操作: 合并操作(插入操作, 取最小操作都是基于合并操作);


左偏树(堆)merge函数具体实现:

--采用递归实现;

--每层递归中, 当roota->val > rootb->val时, 交换roota和rootb;

--向下递归;

--如左子节点距离小于右子节点距离, 交换左右子节点;

--更新本节点距离值;

--返回本节点指针;


斜堆merge函数具体实现:

--采用递归实现(也有非递归算法);

--每层递归中, 当roota->val > rootb->val时, 交换roota和rootb;

--向下递归;

--交换左右子节点;

--返回本节点指针;


左偏树模板如下(只有新建/合并/插入/取堆顶元素/销毁等操作, 没有加入删除功能):

typedef int elemType;
struct leftistTreeNode {
	elemType data;
	unsigned int dist;
	leftistTreeNode *lchild, *rchild;
	leftistTreeNode(const elemType &val): data(val), dist(0), lchild(NULL), rchild(NULL) {}
};
template <typename type>
void swapPtr(type &x, type &y) {
	type t = x;
	x = y; y = t;
}

leftistTreeNode *createLeftistTree(const vector<elemType> &vec);
void destroyLeftistTree(leftistTreeNode *&root);
leftistTreeNode *mergeLeftistTree(leftistTreeNode *&roota, leftistTreeNode *&rootb);
void insertLeftistTreeNode(leftistTreeNode *&root, const elemType &dt);
leftistTreeNode *extractMinNode(leftistTreeNode *&root);

leftistTreeNode *createLeftistTree(const vector<elemType> &vec) {
	leftistTreeNode *root = NULL;
	for (int i = 0; i != vec.size(); ++i)
		insertLeftistTreeNode(root, vec[i]);
	return root;
}
void destroyLeftistTree(leftistTreeNode *&root) {
	leftistTreeNode *left = root->lchild, *right = root->rchild;
	delete(root); root = NULL;
	if (left) destroyLeftistTree(left);
	if (right) destroyLeftistTree(right);
}
leftistTreeNode *mergeLeftistTree(leftistTreeNode *&roota, leftistTreeNode *&rootb) {//核心部分
	if (!roota || !rootb)
		return roota ? roota : rootb;
	if (roota->data > rootb->data)
		swapPtr<leftistTreeNode*>(roota, rootb);//注意: 此处交换的是指针值
	roota->rchild = mergeLeftistTree(roota->rchild, rootb);
	if (!roota->lchild || roota->lchild->dist < roota->rchild->dist)
		swapPtr<leftistTreeNode*>(roota->lchild, roota->rchild);
	if (!roota->rchild)
		roota->dist = 0;
	else
		roota->dist = roota->rchild->dist + 1;
	return roota;
}
void insertLeftistTreeNode(leftistTreeNode *&root, const elemType &dt) {
	leftistTreeNode *cur = new leftistTreeNode(dt);
	root = mergeLeftistTree(root, cur);
}
leftistTreeNode *extractMinNode(leftistTreeNode *&root) {
	leftistTreeNode *min = root;
	root = mergeLeftistTree(root->lchild, root->rchild);
	return min;
}

斜堆模板如下(只有新建/合并/插入/取堆顶元素/销毁等操作, 没有加入删除功能):

typedef int elemType;
struct skewHeapNode {
	elemType data;
	skewHeapNode *lchild, *rchild;
	skewHeapNode(const elemType &val): data(val), lchild(NULL), rchild(NULL) {}
};

template <typename type>
void swapPtr(type &x, type &y) {
	type t = x;
	x = y; y = t;
}

skewHeapNode *createskewHeap(const vector<elemType> &vec);
void destroyskewHeap(skewHeapNode *&root);
skewHeapNode *mergeskewHeap(skewHeapNode *&roota, skewHeapNode *&rootb);
void insertskewHeapNode(skewHeapNode *&root, const elemType &dt);
skewHeapNode *extractMinNode(skewHeapNode *&root);

skewHeapNode *createskewHeap(const vector<elemType> &vec) {
	skewHeapNode *root = NULL;
	for (int i = 0; i != vec.size(); ++i)
		insertskewHeapNode(root, vec[i]);
	return root;
}
void destroyskewHeap(skewHeapNode *&root) {
	skewHeapNode *left = root->lchild, *right = root->rchild;
	delete(root); root = NULL;
	if (left) destroyskewHeap(left);
	if (right) destroyskewHeap(right);
}
skewHeapNode *mergeskewHeap(skewHeapNode *&roota, skewHeapNode *&rootb) {//此处与左偏堆不同, 不判断左右子节点距离
	if (!roota || !rootb)
		return roota ? roota : rootb;
	if (roota->data > rootb->data)
		swapPtr<skewHeapNode*>(roota, rootb);
	roota->rchild = mergeskewHeap(roota->rchild, rootb);
	swapPtr(roota->lchild, rootb->rchild);
	return roota;
}
void insertskewHeapNode(skewHeapNode *&root, const elemType &dt) {
	skewHeapNode *cur = new skewHeapNode(dt);
	root = mergeskewHeap(root, cur);
}
skewHeapNode *extractMinNode(skewHeapNode *&root) {
	skewHeapNode *min = root;
	root = mergeskewHeap(root->lchild, root->rchild);
	return min;
}

最近应该会多发一些学习总结性的内容, 巩固一下知识, 有空把我的学习笔记也发上来供大家参考;

如果算法或分析有问题, 请指正, 谢谢

用AG9311芯片DIY一个多功能Type-C扩展坞:从原理图到PCB布局的保姆级指南 本文详细介绍了如何利用AG9311芯片DIY多功能Type-C扩展坞,涵盖从原理图设计到PCB布局的全过程。AG9311芯片作为高性价比的Type-C控制器,支持HDMI 2.0、USB 3.0、PD快充和千兆网口,适合硬件爱好者打造个性化扩展坞。文章还提供了调试技巧和进阶优化建议,帮助读者轻松完成项目。 阅读详情

相关推荐

AES-GCM加密认证模式:原理、优势与实战应用

在数据安全领域,加密与认证是保障信息机密性和完整性的两大基石。加密确保数据内容不被窃取,而认证则验证数据来源的真实性和传输过程中是否被篡改。传统的加密后认证方案如AES-CBC+HMAC需要串行处理,性能开销较大。GCM(伽罗瓦/计数器模式)作为一种认证加密(AEAD)方案,巧妙地将AES-CTR加密与基于伽罗瓦域的GHASH认证并行结合,实现了单次数据遍历即可同时完成加密和认证,大幅提升了处理效率。其核心价值在于高性能、支持附加认证数据(AAD)以及标准化程度高,广泛应用于TLS协议、无线网络安全和云存储

weixin_28622215的博客 312

python 实现skew heap倾斜堆算法

Skew Heap(倾斜堆)算法是一种特殊的二叉堆数据结构,它通常用于实现优先队列,并支持高效的合并操作。倾斜堆是左倾堆的一个变种,也被称为自适应堆(self-adjusting heap)。定义:倾斜堆是一种二叉树,其中每个节点都有一个键值,并且满足堆序(对于最小堆而言,父节点的键值小于或等于其子节点的键值)。倾斜堆可以是空的,或者由一个根节点和两个子堆组成。主要操作:倾斜堆的主要操作是合并(Merge),即将两个倾斜堆合并为一个新的倾斜堆。

luthane的博客 536

LabVIEW实战:基于DAQmx的实时正弦波生成、采集与波形图动态显示

本文详细介绍了如何使用LabVIEW和DAQmx驱动实现实时正弦波的生成、采集与动态显示。通过USB-6008数据采集卡,结合队列缓冲机制和动态波形图显示技术,构建了一个完整的信号处理系统。文章包含硬件连接、软件配置、任务设置及常见问题排查,适合LabVIEW初学者和硬件控制开发者参考。

weixin_30872337的博客 124

左偏树简介

1、左偏树 1.1定义 左偏数是一颗二叉树,并具有堆性质。左偏树具有两个属性:键值(key)和距离(dist)。 键值(key):用于节点比较大小的属性,类似于堆中节点的键值 外节点:左子树或右子树为空的节点称为外节点,左子树和右子树可以同时为空。所以叶子节点必是外节点,定义外节点的距离值为0,空节点的距离值为-1。空节点即树中不存在的节点,表示为NULL,dist(NULL)=-1 距离(dist):一个不是外节点的距离定义为其到子树中最近的外节点的距离,即两个节点之间路径的权值之和,可以理解外

robator的专栏 4943

一文读懂无人机AI识别算法,原理、技术、应用

本文详细介绍了无人机识别算法的工作原理、技术优势以及在多个行业的应用前景,展现了其在提升安全监控、资源管理和应急响应中的关键作用。尽管无人机识别算法在多个领域展现出巨大潜力,但仍面临技术挑战,如算法的准确性、数据的实时处理能力以及对复杂环境的适应性。4. 消防与城市管理: 无人机识别算法在消防和城市管理中的应用,为相关部门提供了及时的信息支持,提升了应急处置能力和城市管理水平。1. 公安监控: 无人机识别算法在公安领域的应用,可以实时识别犯罪嫌疑人和违法行为,有效提升城市治安管理的智能化水平。

foiadrone的博客 1847

智能座舱-语音交互系统

从什么是智能座舱、智能座舱的发展驱动因素、智能座舱的构成要素三个方面梳理我对智能座舱的基础认识之后,为了加深“智能座舱产品入门”课程中语音交互部分知识的理解,我从什么是语音交互、语音交互的底层技术、智能座舱的语音交互等方面,对智能座舱语音交互系统相关的知识进行了梳理与总结。

GUOSA0928的博客 1440

斜堆

1 斜堆定义: 斜堆是具有堆序性的二叉树, 与左式堆的差别在于没有零路径属性,故 merge操作后,不需要考虑左右子堆的零路径大小,而是无条件交换左右子堆; (干货——斜堆定义) 1.1)定义:斜堆(Skew heap)也叫自适应堆(self-adjusting heap),它是左式堆的一个变种。和左式堆一样,它通常也用于实现优先队列。它的合并操作的时间复杂度也是O(log n)。 1....

miracleon的博客 2166

基于NXP1778的CAN自动波特率检测

一、概念 NXP1778芯片内部自带一个CAN控制器。CAN模块由两部分组成:控制器和验收滤波器。所有的寄存器和RAM都以32位字宽度来访问。 CAN自动波特率检测主要用于以一种CAN的转换的产品中。产品中CAN部分的波特率以前都是通过网页中修改然后配置下去的,依据实际情况的考虑,如果CAN部分的波特率能够根据客户设备的改变而自动改变,将会增加其灵活性。   二、原理 根据CAN控制器的

菜鸟的痕迹专栏 5271

【笔记】左偏树

左偏树本质上是一个二叉堆,支持O1O(1)O1求最值,Olog⁡nO(\log n)Ologn删除最值。不过由于它还支持Olog⁡nO(\log n)Ologn合并两个二叉堆,所以一般左偏树相关的题目都是若干棵左偏树构成森林。左偏树中每个节点维护两个值,点权vvv和与最近空节点的距离distdistdist。点权vvv满足堆性质,即当前点点权小于任意一个儿子的点权。这种二叉堆我们一般称为“小根堆”。

星河依旧长明的博客 1639

三峡大学-微机原理与接口技术实验

其中,A15接E1,因此,A15为1,A14A13A12A11A10A9A8A7通过八输入与非门74LS30与E2连接,因此A14A13A12A11A10A9A8A7为11111111,A6A5A4与CBA连接,因此A6A5A4为101,A3A2A1A0不参与译码,因此IO5的地址范围为1111 1111 1101 0000B~1111 1111 1101 1111B,即0FFD0H~0FFDFH。如图1所示,若IO0输出为低电平,则需要E1接高电平,E2接低电平,E3接低电平,CBA的输入为000。

m0_62222486的博客 495

【以太网硬件九】1000base-X是什么?

简要描述1000base-X物理层规范

highman110的博客 1万+

斜堆(数据结构篇)

讲述数据结构中的斜堆

hellmorning的博客 856

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

【左偏树】讲解

一、左偏树介绍 左偏树(Leftist Tree) 是一种可并堆(Mergeable Heap) ,它除了支持优先队列的三个基本操作(插入,删除,取最小节点),还支持一个很特殊的操作——合并操作。 左偏树是一棵堆有序(Heap Ordered)二叉树。 左偏树满足左偏性质(Leftist Property)。 二、左偏树性质 定义一棵左偏树中的外节点(External Node...

Floraqiu的博客 1031

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

数据结构与算法分析-C++描述 第6章 斜堆ADT(SkewHeap)

斜堆(SkewHeap): 斜堆是左式堆的自调节形式,斜堆和左式堆的关系类似于伸展树和AVL树的关系。斜堆是具有堆序的二叉树,但是不存在对树的结构限制,且不保留零长路径的信息。斜堆的右路径在任何时刻都可以任意长,因此所有操作最坏运行情况为,正如伸展树一样,可以证明(还没证明出来 (┭┮﹏┭┮))对任意M次操作,总的最坏运行情况为,因此每次操作的摊还开销(amortized cost...

qq_37172182的博客 951

左式堆(leftist heap)

堆合并 堆合并是指,对于任意两个堆,将其合并为一个更大的堆,如下图所示: 为了解决这个问题,我们可以首先进行一些初步的尝试。 简明的插入策略 最简明的思路,无非是将一个堆中的元素,逐个删除并且依次插入到另一个堆中。不妨设两个堆的规模分别为m和n,则这种策略的时间复杂度为O(m * (logm + log(m + n))) = O(m * log(m + n))。 Floyd批量建堆算法 ...

Shine__Wong的博客 3888

左偏树

左偏树(Leftist Tree)是一种可并堆(Mergeable Heap) ,它除了支持优先队列的三个基本操作(插入,删除,取最小节点),还支持一个很特殊的操作——合并操作 左偏树是一棵二叉树,它的节点除了和二叉树的节点一样具有左右子树指针( left, right)外,还有两个属性:键值和距离(dist)。键值是用于比较节点的大小。距离则是如下定义的:  节点i称为外节点(ext

不忘初心 1128

斜堆(Skew Heap)

斜堆(Skew Heap)基于左倾堆的概念,也是一个用于快速合并的堆结构,但它可自我调整(self-adjusting),每一个merge操作的平摊成本仍为O(logN),其中N为结点数,而且和左倾堆相比,每个结点没有npl属性,从而节省了空间。斜堆并不能保证左倾,但是每一个合并

ljsspace的专栏 1万+

学习笔记-----左偏树

左偏树概念+基本操作+基础例题

Oops的博客 805

左式堆基础

函数用于判断给定的树是否是左式堆。它使用递归的方式检查每个节点及其子树是否满足左式堆的性质。基于这些性质,我们可以使用递归的方式来判断是否是左式堆。希望这个示例能帮助您理解如何判断一个树是否是左式堆。根据判断结果输出相应的信息。在示例中,我们构建了一个左式堆,并使用。

FJ35092420030205的博客 575

左式堆,斜堆及其合并操作

左式堆是堆的一种,但是左式堆是建立在一个具有堆序性的二叉树上而不是二叉堆 左式堆和二叉堆的共同点: 左式堆具有和二叉堆一样的堆序性 左式堆具有和二叉堆一样的结构性 左式堆和二叉堆的不同点: 左式堆虽然和二叉堆都是二叉树,但是左式堆和二叉堆不同的是,二叉堆接近完全完全二叉树,左式堆是不理想平衡的,更加直接的说,左式堆是趋向于非常不平衡的。 左式堆的一些概念 零路经长(NPL) 左式堆的零...

kevin的博客 4224

左偏树/左倾堆

主要是一般的堆虽然插入、删除、取最值表现较好,但涉及到两个堆进行合并时,时间复杂度较高——左偏堆就是用来解决这个合并的问题的,当然后续还会学习斐波那契堆,那个也能有较好的时间复杂度。由于合并后要形成的也是小顶堆,索引合并好的堆顶还是x,因此递归合并 x的子节点(随便一边都行) 和 y。有两个小顶堆,其中x和y分别为两个小顶堆的堆顶,x.val

qq_43561934的博客 281

十五、【优先级队列】左式堆(leftist heap)

一、左式堆存在的意义 除了标准的插入和删除操作,堆结构在实际应用中的另一个常见的操作是合并,即将堆A和堆B重新组织成一个堆。若采用最基本的完全二叉堆数据结构,其最高效的实现策略是采用Floyd建堆算法将堆A和堆B直接重构成一个新堆,但是该算法的时间复杂度为O(n),这种性能在实际中不让人满意,而左式堆结构能保证在合并操作中只需要调整很少的点,所以能保证合并操作的时间复杂度低至O(logn)。而且...

天涯明月刀的博客 1355

左偏树,可并堆详解,OJ练习,代码详解

左偏树能解决哪些问题

EQUINOX1的博客 1731

算法详解——左偏树

可并堆是啥 给你两个优先队列,要你合并这两个优先队列,而且还要保证合并后符合优先队列的性质,时间复杂度要限制在log⁡(s1+s2)\log (s_1+s_2)log(s1​+s2​)之内。 怎么做?现在普通的堆已经满足不了要求了。 这个时候,就要用一种神奇的数据结构:左偏树了。 (二项堆,斐波那契堆不在本文的考虑范围内) 左偏树 顾名思义...

dilei7762的博客 728
上一篇: LeetCode Jump Game && Jump GameII
下一篇: C++11新特性小结
coderhuhy
博客等级 码龄12年 24粉丝 40原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值