最大堆

数据结构--树(下) 堆、哈夫曼树、哈夫曼编码、并查集

ぃ、小莉子 提交于 2020-02-04 03:13:26
堆(heap) 讲线性结构队列中有提到一种队列叫优先队列(Priority Queue),取出元素是依照元素的优先权大小,而不是元素进入队列的优先顺序。 如何组织优先队列? 我们用完全二叉树去表示优先队列,任一结点都是其子树的最大值/最小值,这就叫堆,堆分为大顶堆和小顶堆,从名字也可看出,大顶对对应的结点顶部为最大值,小顶堆同理。 大顶堆 : 小顶堆 : 堆的两个特性 结构性:用数组表示的完全二叉树 有序性:任一结点的关键字是其子树所有结点的最大值/最小值 堆的抽象数据类型描述 类型名称:最大堆 数据对象集:完美二叉树,每个结点的元素值不小于其他子结点的元素值 操作集: •MaxHeap Create( int MaxSize ):创建一个空的最大堆。 •Boolean IsFull( MaxHeap H ):判断最大堆H是否已满。 •Insert( MaxHeap H, ElementType item ):将元素item插入最大堆H。 •Boolean IsEmpty( MaxHeap H ):判断最大堆H是否为空。 •ElementType DeleteMax( MaxHeap H ):返回H中最大元素(高优先级)。 堆结构 : typedef struct heapsturct { ElementType * Elements ; //0位置存放一个值为无穷大的哨兵

218.天际线问题

我是研究僧i 提交于 2020-01-29 08:40:25
难度:困难 题目描述: 思路总结 : 方法一:暴力(超时) 方法二:最大堆,具体步骤见注释,trick比较多。 题解一:(自写,超时) 思路没啥问题,就是太暴力,没用题目要求用的数据结构,必然会被极端用例逼死。 class Solution : def getSkyline ( self , buildings : List [ List [ int ] ] ) - > List [ List [ int ] ] : #思路:构造一个数据结构,保存Li小于等于cur和Ri大于等于cur,然后每个点找最大,如果是突变点,分为变大变小两种情况,变大,就取大的;变小,就取小的。 cur = 0 pre_val = 0 if not buildings : return [ ] max_val = buildings [ - 1 ] [ 1 ] res = [ ] all_points_val = [ ] for i in range ( max_val + 1 ) : tmp_vals = [ ] tmp_max = 0 for b in buildings : if b [ 0 ] <= cur and b [ 1 ] >= cur : tmp_vals . append ( b [ 2 ] ) all_points_val . append ( tmp_vals ) cur += 1

算法-11-堆排序

心已入冬 提交于 2020-01-29 07:16:56
目录 1、二叉堆 2、堆排序 3、代码 4、应用场景 1、二叉堆 二叉堆是一种特殊的堆,二叉堆是完全二元树(二叉树)或者是近似完全二元树(二叉树)。二叉堆有两种: 最大堆 和 最小堆 。最大堆: 父结点 的键值总是大于或等于任何一个子 节点 的键值 ;最小堆:父结点的键值总是小于或等于任何一个子节点的键值。 二叉堆一般用 数组 来表示 。如果根节点在数组中的位置是1,第 n 个位置的子节点分别在2 n 和 2 n +1。因此,第1个位置的子节点在2和3,第2个位置的子节点在4和5。以此类推。这种基于1的数组存储方式便于寻找父节点和子节点。 下图中a[1]的子结点就是a[2]和a[3]. 2、堆排序 堆排序就是利用了二叉堆中的 最大堆 。即每个父结点(数组中下标k),都要大于等于它的子结点(数组中下标2k和2k+1)。 堆排序的步骤:1、对于一个无序数组a,先将它构建成 最大堆。 这时候二叉堆的 根节点 就是数组中 最大的那个元素 。 2、然后我们把最大的根节点拿出来放在该数组中末尾。 3、将剩下的元素再构建成 最大堆 ,得到第二大元素,放在第一大元素的前面。 4、不断循环。。。。。。。。。。。。。。。。类似冒泡排序的思想,每次先把最大的元素拿出来放在末尾。 3、代码 public class Heap { public static void sort(double[] a){ /

20200126庚子年正月初二 数据结构和算法之利用堆对数组进行快速排序

风格不统一 提交于 2020-01-26 19:47:09
利用堆对数组进行快速排序,以对数组进行升序排序为例,用最大堆可以实现。实现的方法如图所示,一图解千语。先将最大堆的顶结点和尾结点交换,在堆中排除掉尾结点,接着对新的堆进行重新构建一个最大堆。依次类推,直到最后堆的元素个数为0。 在前期代码实现的基础上进行了优化,直接将要排序的数组传进去,不用另外申请额外的空间。完整的代码实现如下: /* 利用堆对数组进行快速排序,以对数组进行升序排序为例,用最大堆 */ # include <Windows.h> # include <iostream> using namespace std ; # define DEFAULT_CAPACITY 100 typedef struct _heap { int * arr ; int size ; //当前已存储的元素个数 int capacity ; //最大的存储容量 } heap ; bool initHeap ( heap & h , int * array , int size ) ; void buildHeap ( heap & h ) ; void adjustHeapDown ( heap & h , int i ) ; void heapSort ( heap & heap ) ; bool popMax ( heap & heap , int & value ) ; int

Java 13新特性概述

蓝咒 提交于 2020-01-14 22:05:17
Java 13 已如期于 2019 年 9 月 17 日正式发布,此次更新是继半年前 Java 12 这大版本发布之后的一次常规版本更新,在这一版中,主要带来了 ZGC 增强、更新 Socket 实现、Switch 表达式更新等方面的改动、增强。 本文主要针对 Java 13 中主要的新特性展开介绍,带你快速了解 Java 13 带来的不同体验。 动态应用程序类-数据共享 在 Java 10 中,为了改善应用启动时间和内存空间占用,通过使用 APP CDS,加大了 CDS 的使用范围,允许自定义的类加载器也可以加载自定义类给多个 JVM 共享使用,具体介绍可以参考 Java 10 新特性介绍 一文详细介绍,在此就不再继续展开 。 Java 13 中对 Java 10 中引入的 应用程序类数据共享进行了进一步的简化、改进和扩展,即:允许在 Java 应用程序执行结束时动态进行类归档,具体能够被归档的类包括:所有已被加载,但不属于默认基层 CDS 的应用程序类和引用类库中的类。通过这种改进,可以提高应用程序类-数据使用上的简易性,减少在使用类-数据存档中需要为应用程序创建类加载列表的必要,简化使用类-数据共享的步骤,以便更简单、便捷地使用 CDS 存档。 在 Java 中,如果要执行一个类,首先需要将类编译成对应的字节码文件,以下是 JVM 装载、执行等需要的一系列准备步骤

40、最小的k个数

穿精又带淫゛_ 提交于 2020-01-08 09:45:47
1、题目描述: 输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。 2、思路: 这道题有三种解法,分别是排序,分治,最大堆(优先队列) 解法一:排序解法,先对输入的数组排序,排序的最快的时间复杂度为o(nlogn),然后取排序后的前k个数。总的时间复杂度为o(nlogn)。 解法二:分治方法,模仿快速排序思想,每次都取数组的第k个数,然后将比第k个数小的数放在数组的左边,比第k个数大的数放在数组的右边。然后不断的调整下去。时间复杂度为O(n)。   这个方法不适合于大数据量,因为需要改变数组的结构,并且要把数组全部加载到内存当中,若内存不够大,就不可以。 解法三:最大堆(优先队列)。首先创建一个容量为k的优先队列,传入比较器,重写其 compare 方法,以保证每次从队列中弹出的元素是最大值。这样优先队列中的元素个数小于k的时候,只需要将数组中取出来的数字直接插入到队列中即可;当优先队列的元素已满,只需要比较堆顶元素和待插入元素,若堆订元素小于待插入元素,那就舍弃,若待插入元素比堆订元素小,那就移除堆订元素,将数组元素插入其中。   这个方法的好处就是不改变数组的结构,内存占用小,适合于海量数据的处理,从最大堆中获取k个数字的最大值的时间复杂度为o(1),而删除和插入元素的操作的时间复杂度为o(logk)

算法导论学习之——堆排序

血红的双手。 提交于 2019-12-31 02:36:34
在这一篇文章中,首先介绍一下堆的属性和性质。然后讲解一下建堆的过程,最后讲解堆排序。 1、堆的介绍 堆的物理存储结构就是一个一维的数组,其数据结构就是一个完全的二叉树。需要注意的是堆中的每个结点不需要后继指针,其父节点和左右孩子结点都可以通过计算得到。假设要计算结点i(i为数组的下标)的父节点和左右孩子结点,可以使用以下公式计算: 在此计算的都是结点的数组下标, 由于堆的数据结构是一个完全二叉树,设该完全二叉树有n个结点。则其内部结点下标分别为:1,2,。。。 故其叶子结点下标分别为: 堆高度:就是从根节点到最长叶子结点的距离。包含N个结点的堆高为: 其次是最大堆和最小堆问题,最大堆就是对任意的父节点的值总是大于或等于孩子节点的值,这样的话就能保证根节点保存堆中的最大元素。 即:A[parent(i)] >=A[i] (最大堆) 同样,最小堆就是对任意的父节点的值小于或等于孩子结点的值,这样就能保证根节点的值最小。 即:A[parent(i)] <=A[i] (最小堆) 一般情况下,最大堆用于堆排序中,最小堆用于优先队列中。 2、建堆 根据堆的性质,我们最终要得到堆的根节点是一个最值,因而,我们需要自底向上进行建堆,若自顶向下建堆的话则不能保证根节点是最值。在此仅讨论建立最大堆的情况。 首先我们可以认为每个叶子结点已经是一个最大堆,然后从最末一个非叶子结点 开始进行对调整

算法导论-堆排序

北慕城南 提交于 2019-12-31 02:36:19
堆排序的时间复杂度是 ,具有空间原址性,即任何时候都只需要常数个额外的元素空间存储临时数据。 一、堆 二叉堆是一个数组,可看成一个近似的完全二叉树,树上的每个结点对应数组中的一个元素。除了最底层外,该树是完全充满的,而且是从左到右填充。 二叉堆可以分为两种形式:最大堆和最小堆。在最大堆中除根节点外所有结点i都要满足: ,即某个结点的值至多与其父结点一样大。在最小堆中除根节点外所有 结点i都要满足: 。 说明: 堆排序中,我们使用最大堆,最小堆通常用于构造优先队列。 二、维护堆的性质 函数MAX-HEAPIFY的输入为一个数组A和下标i,假定根节点为LEFT(i)和RIGHT(i)的二叉树都是最大堆,通过让A[i]的值在最大堆中逐级下降,从而使得以下标i为根结点的子树为最大堆。 函数MAX-HEAPIFY的时间代价包括:调整A[i]、A[LEFT[i]]和A[RIGHT[i]]关系的时间代价 ,加上以一颗i的一个孩子为根结点的子树上运行MAX-HEAPIFY的时间代价(假设递归调用会发生)。 下面首先证明每个子树的大小至多为2n/3。 证明: 设堆的高度为h,最后一层结点个数为m,则整个堆的结点总数为: 。 根结点的左子树结点总数为: , 根结点的右子树结点总数为: ,其中 。 当最底层恰好半满的时候, ,则 , 。 解出: , 。 因此,每个子树的大小至多为2n/3

堆排序(摘自算法导论)

筅森魡賤 提交于 2019-12-31 02:35:58
(二叉)堆是一个数组,他可以被看成一个近似的完全二叉树。树上的每一个节点对应数组中的一个元素,除了最底层之外,该树是完全填满的,而且是从左向右填充。表示堆的数组A包括两个属性,A.length给出数组元素的个数,A.heap-size表示有多少个堆元素存储在该数组中。也就是说,虽然A[1..A.length]可能都有数据,但只有A[1..A.heap-size]中存放的是堆的有效元素。0<=A.heap-size<=A.length。树的根节点是A[1],这样给定一个节点的下标i,我们很容易计算得到它的父节点、左孩子和右孩子的下标。 PARENT(i) return[i/2] LEFT(i) return 2i RIGHT(i) return 2i+1 二叉堆可以分为两种形式:最大堆和最小堆。 在最大堆中,最大堆是指除了根节点之外的所有节点i都要满足 A[PARENT(i)]>=A[i] 也就是说,某个节点的最大值至多与根节点一样大。因此,堆中最大的元素存在根节点中;并且,在任一子树中,该子树所包含的所有节点的值都不大于该子树根节点的值。最小堆的组织方式正好相反 最小堆性质市值除了根节点之外的所有节点i都有 A[PARENT[i]]<=A[i] 在堆排序算法中,我们使用的是最大堆,最小堆通常用于构造优先队列。 如果把堆看成一棵树

堆排序

僤鯓⒐⒋嵵緔 提交于 2019-12-28 04:00:47
http://www.cnblogs.com/skywang12345/p/3602162.html 堆是一种数据结构,其约束(根节点大于左右子节点——大根堆,根节点小于左右子节点——小根堆),一般用完全二叉树表示,用数组直接存储 堆排序包括两部分:1,构造堆,保证堆的性质 2,输出根节点,并调整堆(将根节点与叶子节点调换,堆的性质被打破)使得余下的节点使其仍然构成堆 堆的插入删除 堆的插入:每次插入都是将新数据放在数组最后。可以发现从这个新数据的父结点到根结点必然为一个有序的数列,现在的任务是将这个新数据插入到这个有序数据中——这就类似于 直接插入排序 中将一个数据并入到有序区间中 // 新加入i结点 其父结点为(i - 1) / 2 void MinHeapFixup(int a[], int i) { int j, temp; temp = a[i]; j = (i - 1) / 2; //父结点 while (j >= 0 && i != 0) { if (a[j] <= temp) break; a[i] = a[j]; //把较大的子结点往下移动,替换它的子结点 i = j; j = (i - 1) / 2; } a[i] = temp; } void MinHeapFixup(int a[], int i) { for (int j = (i - 1) / 2; (j