【算法导论】第6章堆排序及利用堆建立最小优先级队列
2012-06-15 15:15
375 查看
1、堆排序
1.1 堆排序简介
堆数据结构是一种数组对象,它可以被视为一棵完全二叉树,树中每个节点与数组A中存放该结点值的那个元素对应。树根为A[1],给定了某个结点的下标i,其父节点PARENT(i),左儿子节点LEFT(i)和右儿子结点RIGHT(i)的下标可以简单的计算出来:PARENT(i):不大于i/2的最大整数,LEFT(i):2i;RIGHT(i):2i+1;
堆排序主要分成三个重要步骤:
(1)利用MAX-HEAPIFY来保持堆的性质:输入为数组A和下标i。当其被调用时,我们假定以LEFT(i)和RIGHT(i)为根的两棵二叉树都是最大堆,但这时A[i]可能小于其子女,这就违反了最大堆性质。MAX-HEAPIFY让A[i]在最大堆中“下降”,使以i为根的子树成为最大堆。
(2)BUILD-MAX-HEAP(A)建堆:自底向上的用MAX-HEAPIFY来将一个数组A[1...n]变成一个最大堆。子数组A[n/2+1...n]中的元素都是树中的叶子,因此每个都可以看做只含一个元素的堆。建堆过程对树中的每一个其他结点都调用一次MAX-HEAPIFY。
(3)HEAPSORT(A):利用(2)已经将数组A造成一个最大堆。因为数组中最大元素在根A[1],则可以通过把它与A
互换来达到最终正确的位置。现在,如果从堆中去掉结点n(通过减小A的大小),可以很容易的将A[1...n-1]建成最大堆。原来的根的子女仍是最大堆,而新的根元素可能违背了最大堆性质,这时调用MAX-HEAPIFY(A,1)就可以保持这一性质,在A[1...(n-1)]中构造出最大堆。
1.2、堆排序具体实现代码:
View Code
3 参考资料:
(1)算法导论
(2)数据结构
1.1 堆排序简介
堆数据结构是一种数组对象,它可以被视为一棵完全二叉树,树中每个节点与数组A中存放该结点值的那个元素对应。树根为A[1],给定了某个结点的下标i,其父节点PARENT(i),左儿子节点LEFT(i)和右儿子结点RIGHT(i)的下标可以简单的计算出来:PARENT(i):不大于i/2的最大整数,LEFT(i):2i;RIGHT(i):2i+1;
堆排序主要分成三个重要步骤:
(1)利用MAX-HEAPIFY来保持堆的性质:输入为数组A和下标i。当其被调用时,我们假定以LEFT(i)和RIGHT(i)为根的两棵二叉树都是最大堆,但这时A[i]可能小于其子女,这就违反了最大堆性质。MAX-HEAPIFY让A[i]在最大堆中“下降”,使以i为根的子树成为最大堆。
(2)BUILD-MAX-HEAP(A)建堆:自底向上的用MAX-HEAPIFY来将一个数组A[1...n]变成一个最大堆。子数组A[n/2+1...n]中的元素都是树中的叶子,因此每个都可以看做只含一个元素的堆。建堆过程对树中的每一个其他结点都调用一次MAX-HEAPIFY。
(3)HEAPSORT(A):利用(2)已经将数组A造成一个最大堆。因为数组中最大元素在根A[1],则可以通过把它与A
互换来达到最终正确的位置。现在,如果从堆中去掉结点n(通过减小A的大小),可以很容易的将A[1...n-1]建成最大堆。原来的根的子女仍是最大堆,而新的根元素可能违背了最大堆性质,这时调用MAX-HEAPIFY(A,1)就可以保持这一性质,在A[1...(n-1)]中构造出最大堆。
1.2、堆排序具体实现代码:
View Code
/*---------------------------------------------- *name:用最小堆实现最小优先级队列 *data:2012-7-3 *author:lp *---------------------------------------------*/ #include<stdio.h> #include<limits.h> #define maxsize 20//最大节点数 int realsize=10;//实际初始时节点数 int parent(int i)//父节点 { return(i/2); } int left(int i)//左子节点 { return(2*i); } int right(int i)//右子节点 { return(2*i+1); } void min_heapify(int p[],int i)//保持堆的性质 { int l,r,little,temp; l=2*i; r=2*i+1; if(l<=realsize && p[l]<p[i]) little=l; else little=i; if(r<=realsize && p[r]<p[little]) little =r; if(little!=i) { temp=p[i]; p[i]=p[little]; p[little]=temp; min_heapify(p,little); } } void build_min_heap(int p[])//建立大顶堆 { int i; for(i=realsize/2;i>0;i--) min_heapify(p,i); } int heap_minimum(int p[])//返回堆中最大值 { return(p[1]); } int heap_extract_min(int p[])//去掉并返回堆中的具有最大关键字的元素 { int min; if(realsize<1) { printf("堆下溢出\n"); return(-1); } min=p[1]; p[1]=p[realsize-1]; realsize--; min_heapify(p,1); return(min); } int heap_decrease_key(int p[],int i,int key)//将元素i的关键字的值增加到key,这里key不能小于原来的值 { int temp; if(key>p[i]) { printf("key的值太大\n"); return(-1); } p[i]=key; while(i>1 && p[parent(i)]>p[i]) { temp=p[i]; p[i]=p[parent(i)]; p[parent(i)]=temp; i=parent(i); } return(0); } void heap_insert(int p[],int key)//将关键字值为key的值插入到堆中 { realsize++; p[realsize]=INT_MAX; heap_decrease_key(p,realsize,key); } void heap_print(int p[])//打印堆 { int i; for(i=1;i<realsize+1;i++) printf("%d ",p[i]); printf("\n"); } void main() { int i,key; int a[maxsize+1]={0,4,1,3,2,16,9,10,14,8,7}; printf("建堆的数据为:\n"); for(i=1;i<realsize+1;i++) printf("%d ",a[i]); printf("\n"); printf("新建成的堆为:\n"); build_min_heap(a); heap_print(a); printf("堆中的最大元素为:\n%d\n",heap_minimum(a)); //printf("堆中取出最大元素后为:\n"); //heap_extract_max(a); //heap_print(a); printf("输入要插入堆的元素:\n"); scanf("%d",&key); heap_insert(a,key); printf("堆中插入元素%d后为:\n",key); heap_print(a); printf("请输入要减小的元素及其要减小的值:\n"); scanf("%d,%d",&i,&key); printf("元素减小之后为:\n"); heap_decrease_key(a,i,key); heap_print(a); }
3 参考资料:
(1)算法导论
(2)数据结构
相关文章推荐
- “用最小堆将k个已排序链表合并为一个排序链表”(算法导论 练习6.5-9)
- 算法导论 8-3思考题 之变长数据项的排序
- 利用Python实现快速算法排序
- 【算法导论】排序---快速排序
- 算法导论_选择排序
- 利用最小编辑距离算法实现文本diff
- 【python菜鸟日记】-02算法导论-选择排序
- 从一个数组中同时找出最大最小数-算法导论第九章
- 排序及相关三(算法导论PS1-3)
- 【算法导论笔记】排序
- 利用C++的基本算法实现十个数排序
- [多图预警详细演示一步一步写算法导论]插入排序
- 算法导论第8章:线性时间排序
- 快速排序的C#实现以及,算法导论上之后一个习题的思考
- 利用Java求最大公约数与最小公倍数的算法
- 算法导论笔记:08线性排序
- 最小生成树(算法导论第23章)
- 【算法导论学习-003】选择排序(SelectionSort)
- 「算法导论」:归并排序
- 算法笔记2-排序-希尔排序(最小增量排序)