首页
学习
活动
专区
圈层
工具
发布

盘点那些必问的数据结构算法题之二叉堆

二叉堆对应的树的根为 A[0],给定某个结点的下标 i ,可以很容易计算它的父亲结点和儿子结点。注意在后面的示例图中我们标注元素是从1开始计数的,而实现代码中是从0开始计数。...为了保持堆的性质,maxHeapify(int A[], int i) 函数让堆数组 A 在最大堆中下降,使得以 i 为根的子树成为最大堆。...= i) { // 最大值不是i,则需要交换i和largest的元素,并递归调用maxHeapify。...终止:过程终止时,i=0,因此结点 0, 1, 2, …, N-1都是最大堆的根,特别的,结点0就是一个最大堆的根。...虽然每次调用 maxHeapify() 时间为 O(lgN),共有 O(N) 次调用,但是说运行时间是 O(NlgN) 是不确切的,准确的来说,运行时间为 O(N),这里就不证明了,具体证明过程参见《算法导论

20310

堆排序与优先队列

假设对于高度为 h 的结点,满足结点数 ,由于堆是一棵完全二叉树,故对于高度为 的结点,有 堆可分为最大堆和最小堆,二者分别满足最大堆性质和最小堆性质。...2.1 maxHeapify 该过程用于维护最大堆性质。即根据输入的结点 iii 维护以 iii 为根的堆的最大堆性质。...2.2 buildMaxHeap 采用自底向上的方法,利用 maxHeapify 过程,将数组 A 构建为一棵最大堆。...根据上文堆的性质可知,堆的叶结点编号分别是 ,故非叶结点的编号为 // 伪代码 buildMaxHeap(A) { A.heapsize = A.length for i...= ⌊A.heapsize/2⌋ downto 1 maxHeapify(A, i) } 因为在高度为 的树上执行 maxHeapify 过程的复杂度为 ,而由上文堆的性质可知

47210
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    【42期】盘点那些必问的数据结构算法题之二叉堆

    二叉堆对应的树的根为 A[0],给定某个结点的下标 i ,可以很容易计算它的父亲结点和儿子结点。注意在后面的示例图中我们标注元素是从1开始计数的,而实现代码中是从0开始计数。...为了保持堆的性质,maxHeapify(int A[], int i) 函数让堆数组 A 在最大堆中下降,使得以 i 为根的子树成为最大堆。...= i) { // 最大值不是i,则需要交换i和largest的元素,并递归调用maxHeapify。...终止:过程终止时,i=0,因此结点 0, 1, 2, …, N-1都是最大堆的根,特别的,结点0就是一个最大堆的根。...虽然每次调用 maxHeapify() 时间为 O(lgN),共有 O(N) 次调用,但是说运行时间是 O(NlgN) 是不确切的,准确的来说,运行时间为 O(N),这里就不证明了,具体证明过程参见《算法导论

    49710

    算法-堆排序的PHP实现

    1.堆(二叉堆):可以视为一棵完全的二叉树,除了最底层之外,每一层都是满的,这使得堆可以利用数组来表示,每一个结点对应数组中的一个元素 2.给出某个结点的下标,可以计算出父结点的和孩子结点的下标; parent...(i)=floor(i/2) left(i)=2i right=2i+1 3.最大堆和最小堆,最大堆:根结点是最大值,最小堆:根结点是最小值 4.堆排序就是把最大堆堆顶的最大数取出,剩余的堆继续调整为最大堆...,再次将堆顶的最大数取出,直到剩余数只有一个结束 5.最大堆调整(维护最大堆,子节点永远小于父结点) ;创建最大堆(把一个数组调整成最大堆的数组);堆排序(创建最大堆,交换,维护最大堆) maxHeapify...> 0; i--) { swap(array, 0, i); //交换第一个和最后一个 maxHeapify(array, 0, i);//维护最大堆,size小了一个...maxHeapify($arr, 0, $i);//维护最大堆,size小了一个 } } //创建最大堆的函数 function buildMaxHeap(&$arr, $heapSize

    60210

    算法导论第六章堆排序(一)

    2)堆分为最大堆和最小堆,最大堆中每一棵子树的父节点的值大于孩子节点,最小堆则相反。 3)表示堆的数组A包括两个属性:A.length和A.heap_size。...4)二叉堆是最常用的,除此之外,还有多叉堆,如习题6-2的d-叉堆。...5)已知一个节点的坐标,容易得到其父节点和孩子节点的坐标:PARENT(i) = i/2; LEFT(i) = 2*i; RIGHT(i)=2*i+1。...堆排序: 为了实现堆排序,需要有这样的几个过程: 1)Build_Max_Heap():建立最大堆,将无序的输入数组构造出一个最大堆; 2)Max_Heapify():维护一个最大堆,即保证满足最大堆的性质...首先,Max_Heapify()是一个很关键的函数,它要保证堆中元素在以后的操作过程中,不管怎么变,都要保证满足最大堆的性质,即父节点的值永远大于孩子节点,知道了这一点,就不难写出代码: 函数原型:Max_Heapify

    907100

    一文讲懂堆排序,解决topK问题

    解题思路 ❝堆排序整个流程可以总结为:上浮下沉 ❞ 为什么解决本题需要用到堆?...❝很多同学可能会想到这样一种解决,我把数组全部排序好,这样就可以拿到第k大的元素,这样是一种解法,但是我们是需要第K大的元素,不一定要全部排序好再去拿,只针对部分元素进行排序,这样的复杂度显然可以降低的...❞ 也就是可以转化为:「使用堆排序来解决这个问题——建立一个大顶堆,做k−1 次删除操作后,堆顶元素就是我们要找的答案」(堆排序过程中,不全部下沉,下沉nums.length-k+1,然后堆顶可以拿到我们...比较时:先让 5 与 9 比较,得到最大的那个,再和 6 比较,发现 9 大于 6,则调整他们的位置。 ?...;i--){ swap(nums,0,i) --heapSize // 下沉后的元素不参与到大顶堆的调整 // 重新调整大顶堆 maxHeapify

    2.7K10

    面试算法:在海量数据中快速查找第k小的条目

    假设从服务器上产生的数据条目数为n,这个值是事先不知道的,唯一确定的是这个值非常大,假定项目需要快速从这n条数据中查找第k小的条目,其中k的值是事先能确定的,请你设计一个设计一个满足需求并且兼顾时间和空间效率的算法...这个题目的难度有若干处,第一是数据数n无法确定,你无法动态的分配合适的空间来存储数据。...在前面的章节中,我们详细讲解过一种数据结构叫堆。回忆一下,这种数据结构有以下特点,第一,它是一只类似于二叉树的结构。...maxHeapify(i); } return heapArray; } public void heapSort() { buildMaxHeap...,将新节点插入到堆中,如果新来的元素值大于根节点,那么就直接忽略掉新元素,于是我们就可以始终保持所遇到的所有元素中排序在前k位的值,最后所有元素的访问完后,我们从堆的根节点处就可以得到海量数据元素中第k

    1.7K40

    算法导论第六章优先队列(二)

    优先队列可以说是堆的一个非常重要的应用,和堆对应,优先队列也分最小优先队列和最大优先队列。...之所以用堆来实现优先队列,我想最大的原因是堆很容易对元素按关键字进行排序。...我们暂且不用管这些奇怪的函数为什么要这么定义,因为这是前人的成功经验总结,肯定是在实际应用中这几个函数用得是最多的,总之,知道这样的四个函数就行了,等用到的时候就知道它们的好处了。...O(lgn),所以,这也是为什么用堆来实现优先队列一个非常重要的原因。...我们采用C++语言,借助STL实现此过程,链表采用vector,最小堆中存放的是vector的迭代器,表示vector中元素的位置。

    86680

    一天一大 leet(数组中的第 K 个最大元素)难度:中等 DAY-29

    示例 示例 1 输入: [3,2,1,5,6,4] 和 k = 2 输出: 5 示例 2 输入: [3,2,3,1,2,4,5,5,6] 和 k = 4 输出: 4 说明: 你可以假设 k 总是有效的,...if (a[j] <= x) { swap(a, ++i, j) } } // 上面的循环如果i等于j其j等于right时,递归时则无法终止 // 则单独替换第i+1上和right...k) } 基于堆排序的选择方法 构造前 k 个最大元素小顶堆,取堆顶,即把最大的 k 个元素依次提到数组顶部 每次取最大推送到顶部 第 k 次时则第 k 大的数在顶部 /** * @param {number...>= 0; --i) { maxHeapify(a, i, len) } } // 指针指向i // 如果两边的数字大于它则用较大的数字替换它 // 递归比较知道查到最大值结束...要补下快速排序和堆排序了。

    47220

    插入、归并、堆、count、radix、快速排序算法运行时间

    (i)=2i,right(i)=2i+1 最大堆:一个节点的值大于它的子节点的值 最小堆:一个节点的值小于它的子节点的值 从一个无序数组构建堆 def buildMaxHeap(self,data)...-1) 复制代码 从length//2+1开始,后面所有的元素都是叶子节点 往前查询的时候,新的元素可能小于它的子节点,需要维持堆的性质 def maxHeapify(self,i,data,heapSize...,这里就是交换下标2和下标4 image.png 再迭代,直到满足堆的性质就可以停止 image.png 构建堆的时间分析 可以看到首先要遍历一半的数组,然后有可能面对从顶层到最底层的一次修正操作...(self): data = self.loadData(self.tsf) # 1构建堆 self.buildMaxHeap(data) # 2排序 self.sort(data)...不是则加入,一直需要判断到k为止,整个过程中需要遍历L,把所有的元素加入新的元素,总共有n个,那么所耗时为O(n+k)。

    57420

    搞定大厂算法面试之leetcode精讲14.排序算法

    O(logn),合并的过程的复杂度是O(n) 分:把数组分成两半,递归子数组,进行分割操作,直到分成一个数 合:把两个字数组合并成一个有序数组,直到全部子数组合并完毕,合并前先准备一个空数组,存放合并之后的结果...数组中的第K个最大元素 (medium) 方法1.维护大小为k的小顶堆,当堆的元素个数小于等于k时,遍历数组,让数组的元素不断加入堆,当堆的大小大于k时,让堆顶元素出列,遍历完数组之后,小顶堆堆顶的元素就是第..., k) { let heapSize = nums.length; buildMaxHeap(nums, heapSize); //构建大顶堆 大小为heapSize //大顶堆...1 maxHeapify(nums, 0, heapSize);//重新heapify } return nums[0];//返回堆顶元素,就是第k大的元素 function...复杂度:时间复杂度O(nlogn),和归并排序的复杂度一样。

    38650

    再谈堆排序:堆排序算法流程步骤透解—最大堆构建原理

    2,其左子节点的下标为  (2*2)+2=6;二叉堆一般分为两种:最大堆和最小堆。...)最小堆堆排序原理堆排序就是把最大堆堆顶的最大数取出,将剩余的堆继续调整为最大堆,再次将堆顶的最大数取出,这个过程持续到剩余数只有一个时结束。...(i/2)最大堆调整(MAX‐HEAPIFY)的作用是保持最大堆的性质,是创建最大堆的核心子程序,作用过程如图所示:Max-Heapify由于一次调整后,堆仍然违反堆性质,所以需要递归的测试,使得整个堆都满足堆性质下面来一个讲解的更加清楚的调整分支节点...2(分支节点2不满足最大堆的性质)默认该分支节点为最大值将2与左右分支比较,从2,12,5中找出最大值,然后和2交换位置根据上面所将的二叉堆性质,分别得到分支节点2的左节点和右节点比较三个节点,得到最大值的下标...因为 Max-Heapify 能够保证下标 i 的结点之后结点都满足最大堆的性质,所以自下而上的调用 Max-Heapify 能够在改造过程中保持这一性质。

    86330

    插入、归并、堆、count、radix、快速排序算法运行时间

    (i)=2i+1 最大堆:一个节点的值大于它的子节点的值 最小堆:一个节点的值小于它的子节点的值 从一个无序数组构建堆 def buildMaxHeap(self,data): length=len...//2+1开始,后面所有的元素都是叶子节点 往前查询的时候,新的元素可能小于它的子节点,需要维持堆的性质 def maxHeapify(self,i,data,heapSize): lChild...移除数组最后一个元素,使得堆大小减1 对头部元素执行一次maxHeapify,恢复最大堆的性质 def maxHeap(self): data = self.loadData(self.tsf)...# 1构建堆 self.buildMaxHeap(data) # 2排序 self.sort(data) def sort(self,data): for i in range(len...不是则加入,一直需要判断到k为止,整个过程中需要遍历L,把所有的元素加入新的元素,总共有n个,那么所耗时为O(n+k)。

    26020

    用javascript分类刷leetcode-排序算法(图文视频讲解)

    O(logn),合并的过程的复杂度是O(n)分:把数组分成两半,递归子数组,进行分割操作,直到分成一个数合:把两个字数组合并成一个有序数组,直到全部子数组合并完毕,合并前先准备一个空数组,存放合并之后的结果...复杂度:时间复杂度O(nlogn),和归并排序的复杂度一样。...nums.length; buildMaxHeap(nums, heapSize); //构建大顶堆 大小为heapSize //大顶堆 前k-1个堆顶元素不断和数组的末尾元素交换 然后重新...1; i--) { swap(nums, 0, i);//交换堆顶和数组末尾元素 --heapSize; //堆大小减1 maxHeapify(nums, 0..., heapSize);//重新heapify } return nums[0];//返回堆顶元素,就是第k大的元素 function buildMaxHeap(nums, heapSize

    57440

    C#语言 十大经典排序算法动画与解析!(动态演示+代码)(java改写成C# )

    排序算法简介 排序算法可以分为内部排序和外部排序。 内部排序是数据记录在内存中进行排序。 而外部排序是因排序的数据很大,一次不能容纳全部的排序记录,在排序过程中需要访问外存。...堆排序 7.1 算法步骤 创建一个堆 H[0……n-1]; 把堆首(最大值)和堆尾互换; 把堆的尺寸缩小 1,并调用 shift_down(0),目的是把新的数组顶端数据调整到相应位置;...(使堆顶元素进入有序区) MaxHeapify(arr, 0, i);//重新将无序区调整为大顶堆 } } ///...{ MaxHeapify(arr, i, arr.Length); //调整大顶堆 } }...arr[large]); //将左右节点中的大者与根节点进行交换(即:实现局部大顶堆) MaxHeapify(arr, large, heapSize);//以上次调整动作的

    57820

    堆排序算法

    啊噢,又开始写算法学习的笔记了。最近在准备面试的过程中又把这些常见的排序算法拿出来复习复习,既然这篇写到了堆排序,那么就代表堆排序算法的概念被我忘的差不多了,写篇博客加深记忆吧。...(image-429679-1533643606451)] 可是原谅我概念真的忘的差不多了,所以理解不了这张图,于是我又找到另一个可视化的过程,一目了然,是别人放在github page上的一个页面,地址就在这里...在堆的数据结构中,堆中的最大值总是位于根节点上。而堆中的一个很重要的操作就是最大堆调整(Max_Heapify),即为将堆的末端子节点作调整,使得子节点永远小于父节点。...接下来看看这个关键的Max_Heapify最大堆调整的实现是怎样的: maxHeapify(start, end) { // 建立父节点指标和子节点指标 let dad = start...this.maxHeapify(son, end); } } 在进行最大堆调整的操作时,我们传入初始和终止的两个索引,并且根据我们刚提到的堆节点的定义,建立父节点和子节点指标。

    79330

    如何用 JS 实现二叉堆

    的父节点,反之 6 和 3 是 2 子节点。...例如:floor( 9 / 2 ) = 4 ,则从下标 4 开始的值都为叶子节点 二叉堆特征 二叉堆是一个完全二叉树,父节点与子节点要保持固定的序关系,并且每个节点的左子树和右子树都是一个二叉堆。...从上图可以看出 图一:每个父节点大于子节点或等于子节点,满足二叉堆的性质 图二:其中有一个父节点小于子节点则不满足二叉堆性质 二叉堆分类 二叉堆根据排序不同,可以分为最大堆和最小堆 最大堆:根节点的键值是所有堆节点键值中最大者...(max); } 形成最大堆 我们可以看到,初始化是由一个数组组成,以下图为例很显然并不会满足最大堆的性质,上述 maxHeapify 函数只是对某一个节点作出对调,无法对整个数组进行重构,所以我们要依次对数组进行递归重构...我们可以通过二叉堆来做排序和优先级队列等。

    1.3K20
    领券