堆(heap)、堆排序(heapSort)、优先级队列
来源:互联网 发布:别墅装修设计软件 编辑:程序博客网 时间:2024/06/08 06:44
1. 堆数据结构: 堆是一种数据结构。分为大根堆和小根堆。
对堆数组,其分布与一个完全二叉树对应,其下标的几个关系:
当i的取值满足区间[1, n]时; 数组的小标从1开始;
parent(i) = i >> 1;
left(i) = 2*i;
right(i) = 2*i +1;
对于C语言的数组的小标从0开始,稍作调整如下:
parent(i) = ( ( (i) - 1 ) >> 1); // i >= 1;
left(i) = ( ( (i) << 1 ) + 1); // i >= 0;
right(i) = ( ( (i) << 1 ) + 2) // i >= 0;
parent(i) = ( ( (i) - 1 ) >> 1); // i >= 1; left(i) = ( ( (i) << 1 ) + 1); // i >= 0; right(i) = ( ( (i) << 1 ) + 2) // i >= 0;
堆的性质:
对于大根堆数组a: 满足: a[parent(i)] >= a[i];
对于小跟堆数组a : 满足: a[parent(i)] <= a[i];
2.堆的构建: 通过堆的调整,完成堆的构建。
堆的构建的两种方式:
1)像插入排序的方式那样进行增量(incremental)求解, 即其满足循环不变式的性质:
总的描述: 数组a[0...j-1]是一个堆,将a[j]加入,通过堆调整,数组a[0...j]也是一个堆。
满足循环不变式的3个条件:
(1)初始化:只有一个a[0]数组a是一个堆。
(2) 保持: 数组a[0...j-1]是一个堆,将a[j]加入,通过堆调整,数组a[0...j]也是一个堆。
(3)终止: 当数组中所有的元素都加入完毕式,整个数组满足堆的性质,是一个堆。
2)合并求解: 以a[i] 为根的拟堆,除a[i] 以外其他所有的元素都满足堆的性质,即除了a[i]以外是以它的两个孩子为根的两个堆。通过堆调整将a[i]加入,形成以a[i]为根的堆。
在数组a中,若数组的元素个数为n,则从a[n/2]、a[n/2 +1] ... a[n-1]满足堆的性质。
满足循环不变式的三个性质:
(1)初始化: 则从a[n/2]、a[n/2 +1] ... a[n-1]满足堆的性质。
(2)保持: 将a[n/2-1] 加入,通过堆调整,从a[n/2-1]、a[n/2]、a[n/2 +1] ... a[n-1]满足堆的性质。
(3)终止:形成以a[0]为根的堆。
算法实现是基于第二种。
3. 堆排序算法: 采用大根堆。首先对数组a[0...n-1]通过2中的方法建立大根堆。
方法: 将a[0...n-1] 中 根元素a[0] 与 a[n-1]交换,则最大元素a[n-1]确定了,
通过堆调整,形成新的堆数组a[0...n-2]. 重复上述过程,最终完成排序。
上述过程是一个循环不变式:
(1)初始化: a[0...n-1] 是个大根堆。
(2)保持:在大根堆a[0...i] 中,将a[i]与a[0]交换确定a[i], 通过调整a[0...i-1]形成新的大根堆。
(3)终止:确定最小的元素a[0].
算法的实现:
/** * \file heapSort.c * * \brief Heap Sort test file */#include <stdio.h>#include <stdlib.h>#define MaxLen 100#define parent(i) (((i)-1)>>1)#define left(i) (((i)<<1) + 1)#define right(i) (((i)<<1) + 2)/** * \brief exchange the value of tow integers. * * \param a integer point. * \param b integer point. */void exchange(int* a, int* b);/** * \brief print an integer array. * * \param a integer array point. * \param len total # of elements of the array. */void printArray(int* a, int len);/** * \brief Max(big) root heap adjust without recurrence. * * \param a array point. * \param i element location. * \param len total # of elements of the array. */void maxHeapify(int* a, int i, int len);/** * \brief Min(small) root heap adjust without recurrence. * * \param a array point. * \param i element location. * \param len total # of elements of the array. */void minHeapify(int* a, int i, int len);/** * \brief Max(big) root heap adjust with recurrence. * * \param a array point. * \param i element location. * \param len total # of elements of the array. */void maxHeapify_r(int* a, int i, int len);/** * \brief Min(small) root heap adjust with recurrence. * * \param a array point. * \param i element location. * \param len total # of elements of the array. */void minHeapify_r(int* a, int i, int len);/** * \brief build max(big) root heap. * * \param a integer array point. * \param len total # of elements of the array. */void buildMaxHeap(int* a, int len);/** * \brief build min(small) root heap. * * \param a integer array point. * \param len total # of elements of the array. */void buildMinHeap(int* a, int len);/** * \brief heap sort in ascending order. * * \param a integer array point. * \param len total # of elements of the array. */void heapSort(int* a, int len);/** * \brief heap sort in decending order. * * \param a integer array point. * \param len total # of elements of the array. */void heapSort_reverse(int* a, int len);int main(int argc, char* argv[]){ int a[] = {3, 4, 8, 6, 7, 1, 2, 5, 9}; int len = 9; heapSort(a, len); //heapSort_reverse(a, len); printArray(a, len); return 0;}void exchange(int* a, int* b) { int tmp; tmp = *a; *a = *b; *b = tmp;}void printArray(int* a, int len) { int i; for(i=0; i<len; i++) { printf("%d\t", a[i]); } printf("\n");}void maxHeapify_r(int *a, int i, int len) { int l; int r; int largest; l = left(i); r = right(i); largest = i; if(l<len && a[largest]<a[l]) largest = l; if(r<len && a[largest]<a[r]) largest = r; if(largest!=i) { exchange(a+largest, a+i); maxHeapify_r(a, largest, len); }}void maxHeapify(int *a, int i, int len) { int l; int r; int largest; int tag; //to indicate the changeable. do{ tag = 0; l = left(i); r = right(i); largest = i; if(l<len && a[largest]<a[l]) largest = l; if(r<len && a[largest]<a[r]) largest = r; if(largest!=i) { exchange(a+largest, a+i); i = largest; tag = 1; } }while(tag);}void minHeapify_r(int* a, int i, int len) { int l; int r; int least; l = left(i); r = right(i); least = i; if(l<len && a[least]>a[l]) least = l; if(r<len && a[least]>a[r]) least = r; if(least!=i) { exchange(a+least, a+i); minHeapify_r(a, least, len); }}void minHeapify(int *a, int i, int len) { int l; int r; int least; int tag; //to indicate the changeable. do{ tag = 0; l = left(i); r = right(i); least = i; if(l<len && a[least]>a[l]) least = l; if(r<len && a[least]>a[r]) least = r; if(least!=i) { exchange(a+least, a+i); i = least; tag = 1; } }while(tag);}void buildMaxHeap(int* a, int len) { int i; int half = (len>>1) -1; for(i=half; i>=0; i--) { maxHeapify(a, i, len); //maxHeapify_r(a, i, len); }}void buildMinHeap(int* a, int len) { int i; int half = (len>>1) -1; for(i=half; i>=0; i--) { minHeapify(a, i, len); //minHeapify_r(a,i, len); }}void heapSort(int *a, int len) { int i; buildMaxHeap(a, len); //printArray(a, len); for(i=len-1; i>0; i--) { exchange(&a[i], &a[0]); len--; maxHeapify(a, 0, len); }}void heapSort_reverse(int *a, int len) { int i; buildMinHeap(a, len); //printArray(a, len); for(i=len-1; i>0; i--) { exchange(&a[i], &a[0]); len--; minHeapify(a, 0, len); }}// usage for priority queue.int maxHeapMaximum(int* a, int len) { return a[0];}int minHeapMinimum(int* a, int len) { return a[0];}int maxHeapExtractMax(int* a, int* len) { int max; if(*len<1) return -1; //heap empty max = a[0]; a[0] = a[*len-1]; *len--; maxHeapify(a, 0, *len); return max;}int minHeapExtractMin(int* a, int* len) { int min; if(*len<1) return -1; //heap empty min = a[0]; a[0] = a[*len-1]; *len--; minHeapify(a, 0, *len); return min;}int maxHeapIncreaseKey(int* a, int i, int len, int key){ if(i>len || key<=a[i]) return -1; int p; a[i] = key; p = parent(i); while(i>0 && a[i]>a[p]) { exchange(a+i, a+p); i = p; p = parent(i); } return 0;}int minHeapDecreaseKey(int* a, int i, int len, int key){ if(i>len || key>=a[i]) return -1; int p; a[i] = key; p = parent(i); while(i>0 && a[i]<a[p]) { exchange(a+i, a+p); i = p; p = parent(i); } return 0;}int maxHeapInsert(int* a, int *len, int key) { int i; int p; *len += 1; if(*len > MaxLen) return -1; i = *len - 1; p = parent(i); a[i] = key; while(i>0 && a[i]>a[p]) { exchange(a+i, a+p); i = p; p = parent(i); } return 0;}int minHeapInsert(int* a, int *len, int key) { int i; int p; *len += 1; if(*len > MaxLen) return -1; i = *len - 1; p = parent(i); a[i] = key; while(i>0 && a[i]<a[p]) { exchange(a+i, a+p); i = p; p = parent(i); } return 0;}int maxHeapDelete(int* a, int i, int* len) { int p; if(i> *len ) return -1; a[i] = a[*len -1]; *len --; maxHeapify(a, i, *len); p = parent(i); while(i>0 && a[i]>a[p]) { exchange(a+i, a+p); i = p; p = parent(i); } return 0;}int minHeapDelete(int* a, int i, int* len) { int p; if(i> *len ) return -1; a[i] = a[*len -1]; *len --; minHeapify(a, i, *len); p = parent(i); while(i>0 && a[i]<a[p]) { exchange(a+i, a+p); i = p; p = parent(i); } return 0;}
4. 用堆数据结构构造优先级队列。
5.用堆构造的优先级队列构造栈、和队列数据结构。
6. 算法分析
堆排序的时间,主要由建立初始堆和反复重建堆这两部分的时间开销构成,它们均是通过调用Heapify实现的。 堆排序的最坏时间复杂度为O(nlogn)。堆序的平均性能较接近于最坏性能。 由于建初始堆所需的比较次数较多,所以堆排序不适宜于记录数较少的文件。 堆排序是就地排序,辅助空间为O(1), 它是不稳定的排序方法。以上参见《算法导论》的第6章。。。
- 堆(heap)、堆排序(heapSort)、优先级队列
- 堆排序(HeapSort)
- 堆排序(Heapsort)
- 堆排序 (Heapsort)
- 堆排序(heapsort)
- 堆排序(HeapSort)
- 堆排序(heapsort)
- 堆排序(heapsort)
- 堆排序(Heapsort)
- 堆排序(HeapSort)
- 堆排序(Heapsort)
- 堆排序(HeapSort)
- 堆排序(heapsort)
- 堆排序(HeapSort)
- 堆排序(1)HeapSort
- HeapSort(堆排序算法)
- HeapSort(堆排序)入门
- 堆(优先级队列)
- 2012年3月份工作总结 ~ 之 ~ PDF 作业对应 (虽然这个作业没有什么意思,但是非常值得总结)
- Red Hat Enterprise Linux 5 通过yum update自动升级
- Source Insight3.5软件使用及配置
- 设计模式学习之GRASP通用职责分配软件模式
- 黑马生活3
- 堆(heap)、堆排序(heapSort)、优先级队列
- u盘 grub win7+Ubuntu11.11安装法 liveusb
- JUnit 4 使用 Java 5 中的注解(annotation)
- Enhancing Parallelism
- 307Sticks(*****)经典DFS+剪枝
- Linux环境下搭建php开发环境
- HTTP协议详解
- Windows7 无法访问局域网共享文件服务器(提示密码错误)
- Reassociation Transformation