堆-优先队列
来源:互联网 发布:冲突世界 知乎 编辑:程序博客网 时间:2024/06/15 15:37
面试的时候被问到了heapsort,发现自己对数据结构这块的理解实在不够,最近打算推翻重新来学一遍。
这里先简单地说一下自己对堆的理解。
堆的特质:
1.平衡二叉树=》保证了操作时间复杂度为logN
2.以最小堆为例,对任意结点,其父节点均小于子节点。=》这样几乎各种操作都是在纵向上(深度)进行的。
由于在堆这个数据结构中,经常需要用到父节点和子节点这个概念,因而为了方便父节点与子节点的取出,当我们把堆存储在数组中时,设置从初始下标由1开始,这样父节点的下标就是子节点下标的一半了。
eg:assume the index of parent is i, then the index of left child is 2*i,and thus right child's 2*i+1
下面的问题:
给一个乱序数组,如何对其进行排序使其满足堆的性质?
我们先把问题化小:给定一个父节点,若已知其左右节点形组成的二叉树满足堆性质,那该如何调节,使得这个父节点组成的二叉树也满足堆性质。
1.若父节点均小于子节点,那么这个父节点以下的堆便满足堆性质。
2.若父节点大于任意一个子节点,那么我们需要交换父子结点,这样引起了一个问题,这个操作会不会打破被交换的子节点以下的堆的性质?如果父节点过大,大于子节点之下的孩子,那么我们还需要对子节点以下的堆进行调整,使其满足堆性质。这样,递归调整下去,直至父节点以下的所有结点都满足堆性质。
void min_heapify(int arr[],int arr_size,int parent){ int left_child=2*(parent+1)-1; int right_child=2*(parent+1); if(left_child>=arr_size) return; int small; int tmp; if(right_child<arr_size&&arr[left_child]>arr[right_child]) small=right_child; else small=left_child; if(arr[small]<arr[parent]){ tmp=arr[parent]; arr[parent]=arr[small]; arr[small]=tmp; min_heapify(arr,arr_size,small); } return;}
回到先前的问题中,我们想构造出一个情景使得我们先前想出的解决方案可以嵌入使用。
我们发现,若我们由下至上地调整结点使其满足堆性质,可以满足我们之前的假设,对给定的一个父节点,其子节点满足堆性质。
那我们就从最后一个父节点推到最前。
如何得到最后一个父节点的下标:
在二叉树中,假设叶节点(度为零的点)共有i个,则度为2点共有i-1个。
证明:
假设二叉树的0度,1度,2度结点为n0,n1,n2,总节点数为T
则有按照结点求和的
T = n0 + n1 + n2 (1)
按照边求和得:
T = n1 + 2 * n2 + 1 (2)
所以 (2) - (1)可得
n2 + 1 - n0 = 0
所以n0 = n2 + 1
当度为1的点有一个时,共有2*i个点,第一个叶节点为第i+1个。设n=2*i,则i+1=n/2+1。
当度为1的点有零个时,共有2*i-1个点,第一个叶节点为第i个。设n=2*i-1,则i=(n+1)/2。
可知,假设总结点数为n,当总结数为偶数时,第n/2+1个为叶节点。当总结点数为奇数时,第(n-1)/2+1=floor(n/2)+1个为叶节点
则我们可以得到第floor(n/2)+1为第一个叶节点,则最后一个父节点为floor(n/2)
void build_heap(int arr[],int arr_size){ int i=floor(arr_size/2); for(i;i>0;i--){ min_heapify(arr,arr_size,i-1); }}
如何进行heapsort:
我们需要将数组分割开来,一部分为继续需要排序的heap,一部分为已经排序好的数组。
在先前的操作中我们可以看到,对于结点的选取调整是基于父节点和子节点下标为一半的关系,所以我们需要传入的heap初始下标最好为1(或者0),这样,我们将每次提取的最小节点放在最后(数组的后半部分),而将需要继续调整的heap放在前面。
void heap_sort(int arr[],int arr_size){ build_heap(arr,arr_size); int tmp; for(int i=arr_size-1;i>0;i--){ tmp=arr[0]; arr[0]=arr[i]; arr[i]=tmp; min_heapify(arr,i,0); }}
由此我们得到了由大至小的数组排序。
- 堆和优先队列
- 堆和优先队列
- 优先队列--二叉堆
- 优先队列--堆
- 二叉堆/优先队列
- 优先队列(堆)
- 优先队列实现堆
- 堆 优先队列
- 优先队列(堆)
- 优先队列与堆
- 优先队列(堆)
- poj3253 堆/优先队列
- 优先队列 - 堆
- 优先队列(堆)
- 优先队列(堆)
- 堆,优先队列
- 堆和优先队列
- 优先队列(堆)
- oracle毫秒数和日期时间之间的转换
- Android广播之接收系统广播(一)
- hnoi2017滚粗记
- linux命令详解之du命令
- [题解]CodeChef APRIL Challenge 17
- 堆-优先队列
- 最大差值
- 洛谷 P2598 [ZJOI2009]狼和羊的故事
- 保留小数精度
- MapleStory引擎-介绍
- 算法之 KMP匹配算法2
- manacher算法----O(n)最长回文串
- Web基础之Servlet深入
- 从jsp页面中连接数据库并进行相关操作(增删查改)