(14)堆

14、二叉树堆的实现与应用详解 本文详细介绍了二叉树堆的理论基础、实现方法及其在优先队列和排序算法中的应用。内容涵盖二叉树堆的基本特性、使用数组表示法进行插入与删除操作的具体实现,以及通过实验室练习加深理解。此外,还讨论了二叉树堆的优化技巧、性能分析、与其他数据结构的对比及常见问题解决方案。最后总结了其应用前景,并提供了直观的可视化示例帮助读者更好地理解和运用这一高效数据结构。 阅读详情

一、简介

    堆数据结构的性质:堆:任何结点的值都小于或等于其孩子的值的完全二叉树为小根堆,任何结点的值都大于或等于其孩子的值的完全二叉树为大根堆。为了方便使用完全二叉树的性质,假定数组从下标1开始。这样:

leftChild = 2*i;
rightChild = 2*i + 1;
parent = i/2;
    堆数据结构算法分析:

    堆排序的最坏时间复杂度为O(nlogn)。堆序的平均性能较接近于最坏性能。由于建初始堆所需的比较次数较多,所以堆排序不适宜于记录数较少的文件。堆排序是就地排序,辅助空间为O(1)。堆排序是不稳定的。

    堆数据结构实现如下所示:

#include"stdio.h"
inline void swap(int &a,int &b)
{
	int temp=a;
        a=b;
        b=temp;
	
}
void HeapAdjust(int array[],int i,int nLength)//自顶向下调整堆
{
	int nChild;
	int nTemp;//赋值为待调整的 节点
	 
	for(nTemp=array[i];2*i<nLength;i=nChild)//2*i<nLength说明还有左孩子
	{
		nChild=2*i;//左孩子  
			
		/*一共两个子节点的话得到 较大的一个*/		   
		if(nChild<nLength-1&&array[nChild+1]>array[nChild])//nChild<nLength-1 判断到头没有
		      ++nChild;
		   
		    /*如果较大子节点大于父节点  将子节点 调整到父节点*/
		if(nTemp<array[nChild])
		      array[i]=array[nChild];
		else
		      break;//这个地方不加 会出错  第一个会输出第二个 
		      
                array[nChild]=nTemp;//子节点 等于父节点 (不执行break)
	} 
}
void HeapSort(int a[],int length)
{
	/*初建堆 */
    for(int i=length/2;i>0;--i)//从最后一个 非叶子节点调整 (这里的  i是下标) 
	   HeapAdjust(a,i,length);
   
    for(int i=length;i>1;--i)
    {
       	  swap(a[1],a[i]);	/*第一个最大元素跟最后一个交换*/

       	  HeapAdjust(a,1,i);//调整堆 (注意 length=i  由于堆是逐渐变小的)
    }
	
}
int main()
{
	int a[10]={0,1,2,5,3,8,4,7,6};
	HeapSort(a,8);
	 
	for(int i=1;i<9;i++)
	   printf("%d\n",a[i]);
	return 0;
}
    利用堆数据结构可实现优先级队列,优先队列是0个或多个元素的集合,每个元素都有一个优先权或值,对优先队列执行的操作有查找、插入一个新元素和删除。在最小优先队列(min priority queue)中,查找操作用来搜索优先权最小的元素,删除操作用来删除该元素;对于最大优先队列(max priority queue),查找操作用来搜索优先权最大的元素,删除操作用来删除该元素。优先权队列中的元素可以有相同的优先权,查找与删除操作可根据任意优先权进行。

    优先级队列代码实现如下所示:

#include <iostream>
using namespace std;
template<class T>

class priqueue {
private:
	int	n, maxsize;
	T	*x;
	void swap(int &i, int &j)//根据坐标交换数组元素的值
	{	T t = i; i = j; j = t; }
public:
	priqueue(int m)//初始化数组
	{	maxsize = m;
		x = new T[maxsize+1];
		n = 0;
	}
        
	void insert(T t)
	{	int i, p;
		x[++n] = t; //插入的元素放到最后
		for (i = n; i > 1 && x[p=i/2] > x[i]; i = p)    
                    swap(x[p], x[i]);
               
	}
        
	T extractmin()//向下调整堆
	{	           
                int i, c;
		T t = x[1];
		x[1] = x[n--];
                
		for (i = 1; (c=2*i) <= n; i = c) {
			if (c+1<=n && x[c+1]<x[c])
				c++;
			if (x[i] <= x[c])
				break;
			swap(x[c], x[i]);
		}
		return t;
	}
        void print(int n)
        {
                for (int i = 1; i < n; i++) //输出堆
                        cout << x[i] << " ";
        }
        
};

template<class T>
void pqsort(T v[], int n)//先初始化一个数组,然后插入建立一个堆
{	priqueue<T> pq(n); 
	int i;
	for (i = 0; i < n; i++)
            pq.insert(v[i]);
        cout<<"输出排序后的堆:";
        pq.print(n);
}

int main()
{	const int	n = 10;
	int	i, v[n];
        /*以下是通过向上调整堆 建立一个10个元素的堆*/
	for (i = 0; i < n; i++)
		v[i] = n-i;      
	pqsort(v, n);
        cout<<"\n执行插入和删除操作(输入0代表删除最小值,输入其他代表插入)"<<endl;
	priqueue<int> pq(100);
        int count=0;
	while (cin >> i)
		if (i == 0)
                {
                    if(count)
                        cout <<"删除的最小元素为:"<<pq.extractmin() << "\n";
                    else
                        cout<<"请先插入元素"<<endl;
                }	
		else
                {
                    pq.insert(i);
                    count++;
                }
	return 0;
}
二、原理

    (1)高效性。堆中所有结点和根结点之间相差的层数在logn之内。因此其执行效率很高,堆排序通过在同一数组中包含两种抽象结构(堆和元素序列)来避免使用额外空间。

    (2)正确性,即堆数据结构的不变性质。

    (3)抽象性。

    (4)过程抽象。

    (5)抽象数据类型。

三、习题

    (1)习题1:实现基于堆的优先级队列,尽可能的提高运行速度。

    为了提高向上调整堆的速度,在x[0]放置哨兵==当前插入的元素。省去了每次都判断i>1,向上调整堆结束:x[p] <= x[i]。代码如下:

void insert(T t) //向上调整堆
{	
    int i, p;
    x[++n] = t; //插入的元素放到最后               
    x[0]=t;        
    for (i = n;  x[p=i/2] > x[i]; i = p)    
        swap(x[p], x[i]);       
}

    (2)习题4:如何使用优先级队列解决下列问题:

    a、构件霍夫曼码;

    b、计算大型浮点数集合的和;

    c、在存有10亿个数的文件中找到最大的100W个数;

    d、将多个较小的有序文件归并为一个较大的有序文件;

    解答:

    a、构造哈夫曼树时候,需要选取当前数组的两个最小值,删除两个最小值,并将计算之和插入原来数组,采用堆,初建堆,两次调用选取最小值的函数。计算之和之后,调用插入堆并调整堆;b、如果将较小浮点数和较大浮点数相加可能造成丢失精度。所以每次取最小的两个相加。然后将和插入数组集合。最后剩下一个就是所有浮点数的和;c、典型的topK;d、将所有小文件要插入的当前值组成一个堆。取堆最小值,插入排序数组。调整堆。然后插入该小文件下一个元素(无后继则不操作)。

    (3)习题7:在一些计算机上,除以2求当前范围的中点是二分搜索程序中开销最大的部分。假设我们已经正确构建了待搜索的数组,说明如何使用乘以2的操作来替代除法。给出建立并搜索这样一个数组的算法。

     修改后的二分搜索从i=1开始,每次迭代将i设置为2i或2i+1.元素x[1]包含中值,x[2]包含第一个四分位值,x[3]包含第三个四分位值,等等。一种能在O(n)时间内将n元有序数组调整为“堆搜索”顺序的算法。作为该方法的先驱,考虑把一个2^k-1元的有序数组a拷贝到一个“堆搜索”数组b中:a中奇数位的元素按顺序放到b的后半部分,模4余2位置的元素按顺序放到b中剩余部分的后半部分,等等。

14、C++ 优先队列与堆的深度解析 本文深入解析了 C++ 中的优先队列(priority_queue)与堆(heap)数据结构,详细介绍了它们的概念、操作方法及实际应用场景。通过代码示例展示了如何构造和使用优先队列与堆,比较了两者之间的异同,并探讨了它们在任务调度、数据筛选等场景中的应用。文章还分析了优先队列与堆的性能特点,帮助开发者在实际编程中灵活选择合适的数据结构。 阅读详情

相关推荐

学习笔记之——Event Camera(事件相机)调研

概述 Event Camera是一种bio-inspired sensor,对应的领域为bio-inspired vision。对于传统的相机,从某种程度上,是捕获一个静态/静止的空间,而Event Camera的目的是:敏感地捕捉运动的物体。 对于传统RGB-camera,相机传回的信息是同步的,所谓同步,就是在某一时刻t,相机会进行曝光,把这一时刻所有的像素填在一个矩阵里回传,一张照片就诞生了。一张照片上所有的像素都对应着同一时刻。至于视频,不过是很多帧的图片,相邻图片间的时间间隔...

gwpscut的博客 3万+

Java14:堆

一 优先级队列(堆) 通过层序遍历将二叉树放入数组中,即使用数组保存二叉树结构。 对于完全二叉树的下标关系: leftChild = 2parent+1; rightChild = 2parent +2; parent = (child-1)/2; 1 堆(heap) 堆逻辑上是一个完全二叉树 堆保存在数组中 任意节点的值都大于其子节点的值,称为大堆 任意节点的值都小于其子节点的值,称为小堆 堆...

长不大的大灰狼 291

从零搭建AMESim与Matlab/Simulink联合仿真环境(2024版软件配置详解)

本文详细介绍了2024年最新版AMESim与Matlab/Simulink联合仿真环境的搭建与配置方法。从软件安装顺序、路径设置到编译器配置,逐步指导如何实现高效联合仿真,特别强调了版本兼容性和环境变量设置等关键细节,帮助工程师快速解决常见问题并优化仿真性能。

weixin_42538752的博客 735

Section 14.堆

一、堆是什么? 堆是一棵完全二叉树 完全二叉树:除了最后一层节点,全部非空的二叉树,且最后一层节点从左往右排布 小根堆:每个节点都小于两个子节点 存储方式:一维数组,下标从1开始,下标x的左子节点是下标2x,右子节点是下标2x+1 二、如何手写一个堆? 初始化,读入堆 for (int i = 1; i <= n; i++) //n是堆的大小 scanf("%d", &h[i]); ::size = n; for (int i = n...

autoAC 521

ADS中HB仿真自动优化报错问题解决心得

在ADS HB仿真中自动优化出现报错被强制暂停,解决方法如下

yyyyyyyyyyjy的博客 6538

某手sig3-ios算法 Chomper黑盒调用

本文主要是介绍Chomper的算法模拟执行,Chomper目前已经已经是能比较完整的模拟ios可执行文件执行的模拟器,在这块有非常大的优势。以前安卓端有强势的unidbg,现在iOS也有Chomper了,后续等待作者持续更新,完善Chomper。强势推荐一波-> Chomper地址: https://github.com/sledgeh4w/chomper。我这块也已经使用Chomper完成雅迪系列、某手的算法调用。后续也会有更多扩展。

成小新的博客 2156

14、编程珠玑笔记十四堆

14、编程珠玑笔记十四堆          本篇名言:“让珊瑚远离惊涛骇浪的侵蚀吗?那无疑是将它们的美丽葬送.”         欢迎转载,转载请标明出处:          使用堆主要用于解决两个问题:排序和优先级队列。          堆是用来表示元素集合的一种数据结构。实际上对中的元素可以是任何有序类型。          作者介绍了二叉树,然后介绍了往二叉树进行插入数值破换二叉

badman250的专栏 3万+

告别“盲开”:手把手教你用MCU内置比较器搞定BLDC无感方波启动(附代码片段)

本文详细介绍了如何利用MCU内置比较器实现BLDC无感方波启动,解决传统无传感器控制中的'盲开'问题。通过虚拟中性点电路设计和三段式启动流程,结合反电动势检测和过零检测技术,提供了一套经济高效的解决方案,并附有可直接移植的代码片段,助力工程师快速实现可靠的无感控制。

weixin_33694172的博客 503

2.14、堆

堆区动态内存分配 1、堆的特性:需要手动开辟和释放空间。 堆区内存 — 生命周期:从你申请开始到释放或者程序结束而结束 作用域:得到的指针范围 2、使用: 必须先申请才能使用 申请: 头文件 :#include <stdlib.h> 函数: malloc 函数五要素: 1).作用:申请堆区内存 2).函数原型: void *malloc(size_t size); 3).参数: size :表示要申请的堆区内存的大小,字节。 4).返回值:void *:万能指针,成功返回–指针指向一.

feiffer·hu的博客 199

Python控制TEMI1000/TEMI1500测试温箱

该温箱是我司从昆山振弘检测设备有限公司采购的TEMI 1000,但是控制器用的是韩国的,关于控温箱这个项目,可参考的资料仅有一份官方的manual,里面包含一些命令格式。只要你有温箱,就应该可以向厂家索取该文档。该温箱的通讯接口只有一个RS232接口,要想实现远程控制,需要有串口转USB的线;类似于下图所以,想依靠python来与之进行通信,还是要通过python 的pyserial库,关于怎么安装pyserial,过于简单,这里不做赘述,可自行百度。

xgh1951的博客 1万+

零基础入门Simulink——基于Simulink的MIMO-OFDM系统仿真建模示例

MIMO概述MIMO技术利用多个天线进行信号发送和接收,通过空间复用来提高数据传输速率,或通过空间分集来增强信号的可靠性。OFDM概述OFDM是一种将高速率数据流分成多个低速数据流并行传输的技术,每个子载波都采用调制方式(如BPSK、QPSK),并通过IFFT/FFT变换实现串并转换。MIMO-OFDM优势结合了MIMO的空间分集增益与OFDM对抗多径效应的能力,适用于宽带无线通信系统。提供了更高的数据速率和更好的频谱效率,是现代无线通信标准(如4G LTE、5G NR等)的核心技术之一。

amy_mhd的博客 888

算法之路_14、堆的基本操作

一、解释 在上一篇博文堆的预备知识 中,我们谈到,堆实际上可以理解为一个数组表示的完全二叉树。他也具有树的一些性质。在这一篇中主要来记录一些堆的基本操作。其中会涉及到上篇博文中阐述到的部分完全二叉树的性质。 二、代码 1、建立一个大根堆 大根堆是堆的两种形式之一。 根节点(亦称为堆顶)的关键字是堆里所有结点关键字中最大者,称为大根堆,又称最大堆(大顶堆)。 大根堆要求根节点的关键字既大...

郭岚的博客 1万+

RK AVS双目融合记录

NOTE] 调试平台双目avs融合调试,需要先保证两个摄像头能正常出图同时出流。使用默认工具测试vi->avs->venc通路是否正常,-a可指定isp效果文件需要开启CONFIG_VIDEO_ROCKCHIP_AVSP和CONFIG_VIDEO_ROCKCHIP_FEC,dts中使能。

mangofu的博客 104

重温算法Day14:堆

堆”(Heap)堆是一个完全二叉树; 堆中每一个节点的值都必须大于等于(或小于等于)其子树中每个节点的值。堆存储:数组中下标为 i 的节点的左子节点,就是下标为 i∗2 的节点,右子节点就是下标为 i∗2+1 的节点,父节点就是下标为 2i​ 的节点。 堆排序:大致分解成两个大的步骤,建堆和排序。建堆:方式1:从下往上堆化:在堆中插入一个元素的思路。尽管数组中包含 n 个数据,但是我们可以假设,起初堆中只包含一个数据,就是下标为 1 的数据。然后,我们调用前面讲的插入操作,将下标从 2 到 n 的数据依.

Linzhongyilisha的专栏 259

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

快排、堆排、归并、优化快排、优化堆排,✨5种方式教你秒解——>【力扣17.14. 最小K个数】

文章目录????毛遂自荐⭐题目????思路✨代码????快速排序????快排分区思想(优化)????堆排序????堆排序(优化)——>构造固定堆????归并排序✨补充知识点????最后 ????毛遂自荐 毛遂自荐一下,给大家推荐一下自己的专栏????,欢迎小伙伴们收藏关注???? 大厂面试题专栏 Java专栏 爬虫专栏 更多专栏尽在主页,点我????!!! ⭐题目 2021-09-13力扣每日一题:面试题 17.14. 最小K个数 ????思路 这题表面上一看,其实就是一

Code皮皮虾的博客 547

计算机控制技术及应用

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

日志 7.14 pwn 堆

调试技巧 pie文件找到基地址的几种方法: 1) gdb-vmmap 2) ps -aux | grep <文件名> //查看pid cd /proc//map_files ll //查看内存映射 ida 可以在.data直接查看已经定义的全局变量,如果全局变量是指针记得查看对应的地址,有时ida会把指针以字符串形式显示出来,这时手动转为十六进制更容易查看 堆题多查看已定义...

RobinZZX的博客 337

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

14 - heapq模块:堆操作

这篇文章围绕堆操作这道算法题展开,梳理解题思路、关键数据结构与复杂度分析,并补充实现时需要注意的边界处理和常见陷阱,适合刷题复盘、面试准备以及快速回顾标准解法。

丨汀、的博客 59

算法通关村第14关【青铜】| 什么是堆

堆构造

Candy___i的博客 262

欧尼酱讲JVM(14)——堆

我以我身上20斤肉发誓,这绝对是全网最全,最详细的有关【堆】的介绍,包含代码举例与JVisualVM演示对象分配过程,有动图,绝对通俗易懂。什么?不信?不信我就瘦20斤给你看!!

化身孤岛的鲸 999

【码道初阶】LeetCode面试题 17.14 最小 K 个数:两种堆解法的“同题不同命”

本文对比了两种堆解法求最小K个数的性能差异。代码1使用小根堆存储所有元素后弹出K次,时间复杂度O(n log n),空间O(n)。代码2维护大小为K的大根堆,仅保留候选最小K个数,时间O(n log k),空间O(k)。当K远小于N时,代码2显著更优。代码1实现简单适合K接近N的情况,代码2则是面试推荐的标准解法,通过大根堆作为"门槛"优化了复杂度。文章还讨论了边界处理、常数优化和快速选择等进阶方案,指出代码2在大多数情况下是最佳实践。

月明长歌的博客 908

Java算法14-高级数据结构:堆

本节课我们介绍另外一种数据结构——堆,注意这里的堆和我们Java语言,C++语言等编程语言在内存中的“堆”是不一样的,这里的堆是一种树,由它实现的优先级队列的插入和删除的时间复杂度都为O(logN),这样尽管删除的时间变慢了,但是插入的时间快了很多,当速度非常重要,而且有很多插入操作时,可以选择用堆来实现优先级队列。 1 堆的定义 ① 它是完全二叉树,除了树的最后一层节点不需要是满的,其它的每一层...

fujiedada的专栏 202

算法导论学习笔记(14)——斐波那契堆

斐波那契堆同二项堆一样,也是一种可合并堆。斐波那契堆的优势是:不涉及删除元素的操作仅需要O(1)的平摊运行时间(关于平摊分析的知识建议看《算法导论》第17章)。和二项堆一样,斐波那契堆由一组树构成。这种堆松散地基于二项堆,说松散是因为:如果不对斐波那契堆做任何DECREASE-KEY 或 DELETE 操作,则堆中每棵树就和二项树一样;但是如果执行这两种操作,在一些状态下必须要破坏二项树的特征,比

xiangzhang321的专栏 4168

算法精解----14、堆

1、用途快速找到最大或最小元素,父节点始终大于或小于左右节点,左右节点之间没有关系。最底层最右端的节点就是最后一个节点。 2、节点成S行自上而下,自左向右顺序编号。元素对应在数组当中。若父节点编号为n,那么左右节点分别为2n+1,2n+2。可以随机访问,虽然属于二叉树,但是不用指针把每个节点串起来体现节点之间的关系。

张勇1234的博客 269

数据结构与算法之美(笔记14)堆的应用

一、优先级队列 我们前面讲过,队列最大的特性就是先进先出。不过,在优先级队列中,数据的出队顺序不是先进先出,而是按照优先级来,优先级最高的,最先出队。 一个堆就可以看做一个优先级队列。很多时候,它们只是概念上的区分而已。往优先级队列中插入一个元素,就相当与往堆中插入一个元素,从优先级队列中取出优先级最高的元素,就相当于取出堆顶元素。 1.合并有序小文件 假设我们有100个文件,每个文件的大...

weixin_42073553的博客 255

14. 对象一定分配在堆中吗?如何判断对象可以被回收

对象一定分配在堆中吗?如何判断对象可以被回收

sinat_33739100的博客 158

算法14--优先级队列(堆)

堆主要用于解决排序和topK问题,topK问题还可以使用快速选择算法解决,其时间复杂度为o(n),但空间复杂度较高。注意是排序后的第 k 大元素,不是第 k 个不同的元素。int add(int val) 将 val 插入数据流 nums 后,返回当前数据流中第 k 大的元素。如果列表的大小是偶数,则没有中间值,中位数是两个中间值的平均值。= y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x。例如 arr = [2,3] 的中位数是 (2 + 3) / 2 = 2.5。

m0_74494481的博客 875
上一篇: (13)搜索
下一篇: 一道有关hash的POJ题目:POJ1200 Crazy Search
ddppqq
博客等级 码龄17年 15粉丝 60原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值