- 浏览: 21241 次
- 性别:
- 来自: 南京
最新评论
在程序设计相关领域,堆(Heap)的概念主要涉及到两个方面:
一种数据结构,逻辑上是一颗完全二叉树,存储上是一个数组对象(二叉堆)。
垃圾收集存储区,是软件系统可以编程的内存区域。
本文所说的堆,指的是前者。
堆排序的时间复杂度是O(nlgN),与快速排序达到相同的时间复杂度。但是在实际应用中,我们往往采用快速排序而不是堆排序。这是因为快速排序的一个好的实现,往往比堆排序具有更好的表现。堆排序的主要用途,是在形成和处理优先级队列方面。另外,如果计算要求是类优先级队列(比如,只要返回最大或者最小元素,只有有限的插入要求等),堆同样是很适合的数据结构。
基础知识
堆一般用数组表示,比如数组A数组的长度Length(A),堆在数组中的元素个数HeapSize(A)。一般说来,HeapSize(A) <= Length(A),因为数组A当中可能有一些元素不在堆中。
假设节点I是数组A中下标为i的节点。
Parent(i) : return Floor(i/2); //I的父节点下标,Floor(i)表示比i小的最大整数。
Left(i) : return 2*i; //I的左子节点
Right(i) : return 2*i+1; //I的右子节点
含有n个元素的堆A的高度是: Floor(lgn)。
堆的基本操作
MaxHeapify( A, i ):
保持堆的性质。假设数组A和下标i,假定以Left(i)和Right(i)为根结点的左右两棵子树都已经是最大堆,节点i的值可能小于其子节点。调整节点i的位置。
BuildMaxHeap( A ):
从一个给定的数组建立最大堆。子数组A[ floor(n/2)+1 .... ... n]中的元素都是树的叶节点(完全二叉树的基本性质)。从索引 ceiling(n/2)开始一直到1,对每一个元素都执行MaxHeapify,最终得到一个最大堆。
堆排序 HeapSort( A ):
堆排序算法的基本思想是,将数组A创建为一个最大堆,然后交换堆的根(最大元素)和最后一个叶节点x,将x从堆中去掉形成新的堆A1,然后重复以上动作,直到堆中只有一个节点。
优先级队列算法-增加某元素的值(优先级) : HeapIncreaseKey( A, i, key )
增加某一个元素的优先级后(元素的值),该元素应该向上移动,才能保持堆的性质。
优先级队列算法-插入一个元素: Insert( S, x ) 将x元素插入到优先级队列S中。
主要思路是,将堆的最后一个叶节点之后,扩展一个为无穷小的新叶节点,然后增大它的值为x的值。
堆排序实现原理
堆排序的C语言实现
view sourceprint?01 #include <stdio.h>
02 #include <stdlib.h>
03
04 void HeapSort(int num[],int size);
05 void BuildHeap(int num[] ,int size);
06 void PercolateDown(int num[] , int index,int size);
07 void PrintHeap(const char* strMsg,int array[],int nLength);
08 void Swap(int num[] , int v, int u);
09
10 int main(int argc, char *argv[])
11 {
12 int data[13]={8,5,4,6,13,7,1,9,12,11,3,10,2};
13 HeapSort(data,13);
14
15 system("PAUSE");
16 return 0;
17 }
18
19
20 void HeapSort(int num[] ,int size)
21 {
22 int i;
23 int iLength=size;
24
25 PrintHeap("Befor Sort:",num,iLength);
26
27 BuildHeap(num,size);// 建立小顶堆
28
29 for (i = iLength - 1; i >= 1; i--) {
30 Swap(num, 0, i);// 交换
31 size--;// 每交换一次让规模减少一次
32 PercolateDown(num, 0,size);// 将新的首元素下滤操作
33 PrintHeap("Sort Heap:",num,iLength);
34 }
35 }
36
37 // 建堆方法,只需线性时间建好
38 void BuildHeap(int num[] ,int size) {
39 int i;
40 for (i = size / 2 - 1; i >= 0; i--) {// 对前一半的节点(解释为“从最后一个非叶子节点开始,将每个父节点都调整为最小堆”更合理一些)
41 PercolateDown(num, i,size);// 进行下滤操作
42 PrintHeap("Build heap:",num,size);
43 }
44 }
45
46 // 对该数进行下滤操作,直到该数比左右节点都小就停止下滤
47 void PercolateDown(int num[] , int index,int size) {
48 int min;// 设置最小指向下标
49 while (index * 2 + 1<size) {// 如果该数有左节点,则假设左节点最小
50 min = index * 2 + 1;// 获取左节点的下标
51 if (index * 2 + 2<size) {// 如果该数还有右节点
52 if (num[min] > num[index * 2 + 2]) {// 就和左节点分出最小者
53 min = index * 2 + 2;// 此时右节点更小,则更新min的指向下标
54 }
55 }
56 // 此时进行该数和最小者进行比较,
57 if (num[index] < num[min]) {// 如果index最小,
58 break;// 停止下滤操作
59 } else {
60 Swap(num, index, min);// 交换两个数,让大数往下沉
61 index = min;// 更新index的指向
62 }
63 }// while
64 }
65
66 // 给定数组交换两个数的位置
67 void Swap(int num[] , int v, int u) {
68 int temp = num[v];
69 num[v] = num[u];
70 num[u] = temp;
71 }
72
73 void PrintHeap(const char* strMsg,int array[],int nLength)
74 {
75 int i;
76 printf("%s",strMsg);
77 for(i=0;i<nLength;i++)
78 {
79 printf("%d ",array[i]);
80 }
81 printf("\n");
82 }
下面也是C语言的实现,稍微改动了下:
view sourceprint?01 #include <stdio.h>
02 #include <stdlib.h>
03
04 void HeapSort(int num[],int size);
05 void BuildHeap(int num[] ,int size);
06 void PercolateDown(int num[] , int index,int size);
07 void PrintHeap(const char* strMsg,int array[],int nLength);
08 void Swap(int num[] , int v, int u);
09
10 int main(int argc, char *argv[])
11 {
12 /* 将数组看成完全二叉树的中序遍历结果的线性存储 */
13 int data[13]={8,5,4,6,13,7,2,9,12,11,3,10,1};
14 HeapSort(data,13);
15
16 system("PAUSE");
17 return 0;
18 }
19
20
21 void HeapSort(int num[] ,int size)
22 {
23 int i;
24 int iLength=size;
25
26 PrintHeap("Befor Sort:",num,iLength);
27
28 BuildHeap(num,size);// 建立小顶堆
29
30 for (i = iLength - 1; i >= 1; i--) {
31 Swap(num, 0, i);// 交换
32 size--;// 每交换一次让规模减少一次
33 PercolateDown(num, 0,size);// 将新的首元素下滤操作
34 PrintHeap("Sort Heap:",num,iLength);
35 }
36 }
37
38 /* 建堆方法,只需线性时间建好;
39 建堆的结果:数组的第一个元素(即树根)是所有元素中的最小值,索引小于等于size/2-1的其它元素(即其它非叶子节点)的值都是其所在子树的最小值 */
40 void BuildHeap(int num[] ,int size) {
41 int i;
42 //从最后一个非叶子节点开始,对每个非叶子节点进型最小根调整,保证每个根节点都是其子树中的最小值
43 for (i = size / 2 - 1; i >= 0; i--) {
44 PercolateDown(num, i,size);// 进行下滤操作
45 PrintHeap("Build heap:",num,size);
46 }
47 }
48
49 /* 对该数进行下滤操作,直到该数比左右节点都小就停止下滤。
50 即对某个根节点的值进行位置下降调整,使该值比其左右子节点都小;
51 若该节点是叶子节点,则无法while循环 */
52 void PercolateDown(int num[] , int index,int size) {
53 int min;// 设置最小指向下标
54 while (index * 2 + 1<size) {// 如果该数有左节点,则假设左节点最小
55 min = index * 2 + 1;// 获取左节点的下标
56 if (index * 2 + 2<size) {// 如果该数还有右节点
57 if (num[min] > num[index * 2 + 2]) {// 就和左节点分出最小者
58 min = index * 2 + 2;// 此时右节点更小,则更新min的指向下标
59 }
60 }
61 // 此时进行该数和最小者进行比较,
62 if (num[index] < num[min]) {// 如果index最小,
63 break;// 停止下滤操作
64 } else {
65 Swap(num, index, min);// 交换两个数,让大数往下沉
66 index = min;// 更新index的指向
67 }
68 }// while
69 }
70
71 // 给定数组交换两个数的位置
72 void Swap(int num[] , int v, int u) {
73 int temp = num[v];
74 num[v] = num[u];
75 num[u] = temp;
76 }
77
78 void PrintHeap(const char* strMsg,int array[],int nLength)
79 {
80 int i;
81 printf("%s",strMsg);
82 for(i=0;i<nLength;i++)
83 {
84 printf("%d ",array[i]);
85 }
86 printf("\n");
87 }
一种数据结构,逻辑上是一颗完全二叉树,存储上是一个数组对象(二叉堆)。
垃圾收集存储区,是软件系统可以编程的内存区域。
本文所说的堆,指的是前者。
堆排序的时间复杂度是O(nlgN),与快速排序达到相同的时间复杂度。但是在实际应用中,我们往往采用快速排序而不是堆排序。这是因为快速排序的一个好的实现,往往比堆排序具有更好的表现。堆排序的主要用途,是在形成和处理优先级队列方面。另外,如果计算要求是类优先级队列(比如,只要返回最大或者最小元素,只有有限的插入要求等),堆同样是很适合的数据结构。
基础知识
堆一般用数组表示,比如数组A数组的长度Length(A),堆在数组中的元素个数HeapSize(A)。一般说来,HeapSize(A) <= Length(A),因为数组A当中可能有一些元素不在堆中。
假设节点I是数组A中下标为i的节点。
Parent(i) : return Floor(i/2); //I的父节点下标,Floor(i)表示比i小的最大整数。
Left(i) : return 2*i; //I的左子节点
Right(i) : return 2*i+1; //I的右子节点
含有n个元素的堆A的高度是: Floor(lgn)。
堆的基本操作
MaxHeapify( A, i ):
保持堆的性质。假设数组A和下标i,假定以Left(i)和Right(i)为根结点的左右两棵子树都已经是最大堆,节点i的值可能小于其子节点。调整节点i的位置。
BuildMaxHeap( A ):
从一个给定的数组建立最大堆。子数组A[ floor(n/2)+1 .... ... n]中的元素都是树的叶节点(完全二叉树的基本性质)。从索引 ceiling(n/2)开始一直到1,对每一个元素都执行MaxHeapify,最终得到一个最大堆。
堆排序 HeapSort( A ):
堆排序算法的基本思想是,将数组A创建为一个最大堆,然后交换堆的根(最大元素)和最后一个叶节点x,将x从堆中去掉形成新的堆A1,然后重复以上动作,直到堆中只有一个节点。
优先级队列算法-增加某元素的值(优先级) : HeapIncreaseKey( A, i, key )
增加某一个元素的优先级后(元素的值),该元素应该向上移动,才能保持堆的性质。
优先级队列算法-插入一个元素: Insert( S, x ) 将x元素插入到优先级队列S中。
主要思路是,将堆的最后一个叶节点之后,扩展一个为无穷小的新叶节点,然后增大它的值为x的值。
堆排序实现原理
堆排序的C语言实现
view sourceprint?01 #include <stdio.h>
02 #include <stdlib.h>
03
04 void HeapSort(int num[],int size);
05 void BuildHeap(int num[] ,int size);
06 void PercolateDown(int num[] , int index,int size);
07 void PrintHeap(const char* strMsg,int array[],int nLength);
08 void Swap(int num[] , int v, int u);
09
10 int main(int argc, char *argv[])
11 {
12 int data[13]={8,5,4,6,13,7,1,9,12,11,3,10,2};
13 HeapSort(data,13);
14
15 system("PAUSE");
16 return 0;
17 }
18
19
20 void HeapSort(int num[] ,int size)
21 {
22 int i;
23 int iLength=size;
24
25 PrintHeap("Befor Sort:",num,iLength);
26
27 BuildHeap(num,size);// 建立小顶堆
28
29 for (i = iLength - 1; i >= 1; i--) {
30 Swap(num, 0, i);// 交换
31 size--;// 每交换一次让规模减少一次
32 PercolateDown(num, 0,size);// 将新的首元素下滤操作
33 PrintHeap("Sort Heap:",num,iLength);
34 }
35 }
36
37 // 建堆方法,只需线性时间建好
38 void BuildHeap(int num[] ,int size) {
39 int i;
40 for (i = size / 2 - 1; i >= 0; i--) {// 对前一半的节点(解释为“从最后一个非叶子节点开始,将每个父节点都调整为最小堆”更合理一些)
41 PercolateDown(num, i,size);// 进行下滤操作
42 PrintHeap("Build heap:",num,size);
43 }
44 }
45
46 // 对该数进行下滤操作,直到该数比左右节点都小就停止下滤
47 void PercolateDown(int num[] , int index,int size) {
48 int min;// 设置最小指向下标
49 while (index * 2 + 1<size) {// 如果该数有左节点,则假设左节点最小
50 min = index * 2 + 1;// 获取左节点的下标
51 if (index * 2 + 2<size) {// 如果该数还有右节点
52 if (num[min] > num[index * 2 + 2]) {// 就和左节点分出最小者
53 min = index * 2 + 2;// 此时右节点更小,则更新min的指向下标
54 }
55 }
56 // 此时进行该数和最小者进行比较,
57 if (num[index] < num[min]) {// 如果index最小,
58 break;// 停止下滤操作
59 } else {
60 Swap(num, index, min);// 交换两个数,让大数往下沉
61 index = min;// 更新index的指向
62 }
63 }// while
64 }
65
66 // 给定数组交换两个数的位置
67 void Swap(int num[] , int v, int u) {
68 int temp = num[v];
69 num[v] = num[u];
70 num[u] = temp;
71 }
72
73 void PrintHeap(const char* strMsg,int array[],int nLength)
74 {
75 int i;
76 printf("%s",strMsg);
77 for(i=0;i<nLength;i++)
78 {
79 printf("%d ",array[i]);
80 }
81 printf("\n");
82 }
下面也是C语言的实现,稍微改动了下:
view sourceprint?01 #include <stdio.h>
02 #include <stdlib.h>
03
04 void HeapSort(int num[],int size);
05 void BuildHeap(int num[] ,int size);
06 void PercolateDown(int num[] , int index,int size);
07 void PrintHeap(const char* strMsg,int array[],int nLength);
08 void Swap(int num[] , int v, int u);
09
10 int main(int argc, char *argv[])
11 {
12 /* 将数组看成完全二叉树的中序遍历结果的线性存储 */
13 int data[13]={8,5,4,6,13,7,2,9,12,11,3,10,1};
14 HeapSort(data,13);
15
16 system("PAUSE");
17 return 0;
18 }
19
20
21 void HeapSort(int num[] ,int size)
22 {
23 int i;
24 int iLength=size;
25
26 PrintHeap("Befor Sort:",num,iLength);
27
28 BuildHeap(num,size);// 建立小顶堆
29
30 for (i = iLength - 1; i >= 1; i--) {
31 Swap(num, 0, i);// 交换
32 size--;// 每交换一次让规模减少一次
33 PercolateDown(num, 0,size);// 将新的首元素下滤操作
34 PrintHeap("Sort Heap:",num,iLength);
35 }
36 }
37
38 /* 建堆方法,只需线性时间建好;
39 建堆的结果:数组的第一个元素(即树根)是所有元素中的最小值,索引小于等于size/2-1的其它元素(即其它非叶子节点)的值都是其所在子树的最小值 */
40 void BuildHeap(int num[] ,int size) {
41 int i;
42 //从最后一个非叶子节点开始,对每个非叶子节点进型最小根调整,保证每个根节点都是其子树中的最小值
43 for (i = size / 2 - 1; i >= 0; i--) {
44 PercolateDown(num, i,size);// 进行下滤操作
45 PrintHeap("Build heap:",num,size);
46 }
47 }
48
49 /* 对该数进行下滤操作,直到该数比左右节点都小就停止下滤。
50 即对某个根节点的值进行位置下降调整,使该值比其左右子节点都小;
51 若该节点是叶子节点,则无法while循环 */
52 void PercolateDown(int num[] , int index,int size) {
53 int min;// 设置最小指向下标
54 while (index * 2 + 1<size) {// 如果该数有左节点,则假设左节点最小
55 min = index * 2 + 1;// 获取左节点的下标
56 if (index * 2 + 2<size) {// 如果该数还有右节点
57 if (num[min] > num[index * 2 + 2]) {// 就和左节点分出最小者
58 min = index * 2 + 2;// 此时右节点更小,则更新min的指向下标
59 }
60 }
61 // 此时进行该数和最小者进行比较,
62 if (num[index] < num[min]) {// 如果index最小,
63 break;// 停止下滤操作
64 } else {
65 Swap(num, index, min);// 交换两个数,让大数往下沉
66 index = min;// 更新index的指向
67 }
68 }// while
69 }
70
71 // 给定数组交换两个数的位置
72 void Swap(int num[] , int v, int u) {
73 int temp = num[v];
74 num[v] = num[u];
75 num[u] = temp;
76 }
77
78 void PrintHeap(const char* strMsg,int array[],int nLength)
79 {
80 int i;
81 printf("%s",strMsg);
82 for(i=0;i<nLength;i++)
83 {
84 printf("%d ",array[i]);
85 }
86 printf("\n");
87 }
发表评论
-
KMP快速字符串查找算法
2011-08-25 19:29 640在C/C++语言编程过程中,一般的字符串搜索操作都是通过标准库 ... -
求解最大公约数问题
2011-08-25 19:27 661最大公因数,又称最大公约数。是指 [n(≧2)个自然数 a1, ... -
整数拆分问题的动态规划解法
2011-08-25 19:26 3034输入n,和k,问将n用1到k这k个数字进行拆分,有多少种拆分方 ... -
背包问题介绍与分析
2011-08-25 19:24 1001背包问题是在1978年由Merkel和Hellman提出的。它 ... -
求平方根sqrt()函数的底层算法效率问题
2011-08-25 19:23 1264我们平时经常会有一些数据运算的操作,需要调用sqrt,exp, ... -
面试中常见的一些算法问题
2011-08-25 19:22 672Problem 1 : Is it a loop ? ( ... -
各种排序算法的C++实现与性能比较
2011-08-25 19:21 890排序是计算机算法中非常重要的一项,而排序算法又有不少实现方法, ... -
背包问题之硬币找零问题
2011-08-25 19:19 1129设有6 种不同面值的硬 ... -
求能被1到20的数整除的最小正整数
2011-08-25 19:18 1337求能被1到20的数整除的最小正整数。最直觉的方法是求1到20这 ... -
买书折扣最优惠问题解法
2011-08-25 19:17 720题目:在节假日的时候 ... -
二叉树中的最近公共祖先问题
2011-08-25 19:16 1293题目:要求寻找二叉树中两个节点的最近的公共祖先,并将其返回。 ... -
判断一个整数是否是2的N次方
2011-08-25 19:04 1789题目:给定一个整数num,判断这个整数是否是2的N次方。比如, ... -
字符串逆序的算法汇总
2011-08-25 19:01 1034很早就准备写一个字符串系列的面试题,本来已经写好了,大概有十几 ... -
计算从1到N中1的出现次数
2011-08-25 18:59 573给定一个十进制整数N, ... -
KMP快速字符串查找算法
2011-08-25 18:57 939在C/C++语言编程过程中,一般的字符串搜索操作都是通过标准库 ... -
快速排序的递归实现
2011-08-25 18:54 728快速排序是对冒泡排序的一种改进。它的基本思想是:通过一次排序将 ... -
数字1亿里面有多少个1呢
2011-08-25 18:52 710乍看这题真够唬人的,群里看到这个题目后争先恐后的说看法。最简单 ... -
最大子序列、最长公共子串、最长公共子序列
2011-08-25 18:33 754最大子序列 最大子序列是要找出由数组成的一维数组中和最大的连续 ... -
一道关于男女比例的面试题
2011-08-25 16:56 1016阿里巴巴的一道面试题:说澳大利亚的父母喜欢女孩,如果生出来的第 ...
相关推荐
堆排序 堆排序(Heap Sort)是一种基于二叉堆数据结构的排序算法
我刚用C#写的堆排序算法(HEAPSORT),算法简洁,质量不错,只是注释不多
void heap_sort(int A[],int length) { BUILD_MAX_HEAP(A,length); int i,middle; for(i=length-1;i>0;i--) { middle=A[0]; A[0]=A[i]; A[i]=middle; heap_size--; MAX_HEAPIFY(A,0); } }
经典排序算法 - 堆排序Heap sort序 经典排序算法 - 地精排序Gnome Sort 经典排序算法 - 奇偶排序Odd-even sort 经典排序算法 - 梳排序Comb sort 经典排序算法 - 耐心排序Patience Sorting 经典排序算法 - 珠...
主要为大家详细介绍了PHP实现排序堆排序(Heap Sort)算法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
用C++实现的 堆排序,包括恢复堆,构建初始堆
主要介绍了PHP排序算法之堆排序(Heap Sort),结合实例形式详细分析了堆排序的原理、实现方法及相关使用注意事项,需要的朋友可以参考下
排序算法 - 快速排序(Insert Sort) - 希尔排序(Shell Sort) - 冒泡排序(Bubble Sort) - 快速排序(Quick Sort) - 选择排序(Selection Sort) - 堆排序(Heap Sort) - 归并排序(Merge Sort) - 箱排序(Bin Sort) - 基数...
堆排序(Heapsort)是指利用堆这种数据结构(后面的【图解数据结构】内容会讲解分析)所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的...
heap Sort. In briefly, it had been done with java.
以图文详解Heap Sort堆排序算法及JavaScript的代码实现,堆排序算法基于类二叉树的堆数据结构,需要的朋友可以参考下
堆排序,C语言写成。 凑字数真的很难,我觉得我已经说的很清楚了。
堆排序算法Java实现
堆排序算法的java实现,采用大根堆。时间复杂度为O(nlogn).
各种排序算法,包括希尔算法,快速排序,堆排序-A variety of sorting algorithms, including the Hill algorithm, quick sort, heap sort
C++ 堆排序
c++ code for MaxHeap Sort