算法导论第六章6.5有限队列中的6.5-9课后练习
2014-01-05 14:20
417 查看
由题目提示知,需要用到归并排序,又要用到最小堆,那么我想到用含有最小堆排序的归并排序对k个有序数组进行合并因为链表可以看成特殊的动态数组,那么我把链表替换成数组求解。先把k个数组放入到一个新数组A中,那么一共就有k=n/a个数组(a为k个元素数组中所含最多元素的数量)
注释1:详情见这个是带有插入排序的归并算法(此链接里面的k元素长度值相当于这里的a元素长度值)也就是每个有序数组(共k个)含有有效元素的长度不能大于总元素的开方,这是能够正确进行归并排序的先决条件。这个归并排序,运行时间为O(nlgn),没有到达O(nlgk),实在想不出如何缩短运行时间的方法了。
#include <iostream> using namespace std; const length=100; int LEFT(int i); int RIGHT(int i); void MIN_HEAPIFY(int A[],int i); void BUILD_MIN_HEAP(int A[],int p,int q); int* HEAPSORT(int A[],int B[],int p,int q,int r); void MERGE(int A[],int p,int q,int r); void MERGE_SORT(int A[],int p,int r,int k); int heap_size=length,a=4; void main() { int B[8][4]={{8,16,19},{1,9},{2,10,17,20},{3,11},{4,12},{5,13},{6,14,18},{7,15}};//这是k=8个数组在一个2维数组中 int A[length]={0}; for(int i=0,h=0;i<8;i++)//将k=8个数组合并到一个新数组中。 { for (int j=0;j<4;j++,h++) { if(B[i][j]!=0) A[h]=B[i][j]; } }//这个双重循环含k*a=n个元素 运行时间为O(n) MERGE_SORT(A,0,length-1,a);//然后将新数组每a=4个有序数进行归并,注意a值的选择 2<=a<=√总元素n (注释1) cout<<"排序后:"<<endl; for ( i=0;i<length;i++) { if(A[i]>0) cout<<A[i]<<" "; } cout<<endl; } int LEFT(int i) { return 2*i+1; } int RIGHT(int i) { return 2*i+2; } void MIN_HEAPIFY(int A[],int i) { int largest=0; int L=LEFT(i); int R=RIGHT(i); if (L<heap_size&&A[L]<A[i]) { largest=L; } else largest=i; if (R<heap_size&&A[R]<A[largest]) { largest=R; } if (largest!=i) { swap(A[i],A[largest]); MIN_HEAPIFY(A,largest); } } void BUILD_MIN_HEAP(int A[],int p,int q) { heap_size=q; for (int i=q/2;i>=p;i--) { MIN_HEAPIFY(A,i); } } int* HEAPSORT(int A[],int B[],int p,int q,int r) { for (int i=p,j=0;i<=q,j<r;i++,j++) { B[j]=A[i]; } BUILD_MIN_HEAP(B,0,r); for ( i=r-1;i>=1;i--) { swap(B[0],B[i]); heap_size--; MIN_HEAPIFY(B,0); } return B; } void MERGE(int A[],int p,int q,int r) { int n1=q-p+1,n2=r-q,i,j,flag=-1; int *L=new int[n1]; int *R=new int[n2]; L=HEAPSORT(A,L,p,q,n1);//归并时,用最小堆排序 R=HEAPSORT(A,R,q+1,r,n2); i=0;j=0; L[n1]=flag; R[n2]=flag; for (int k=p;k<=r;k++) { if (L[i]==flag) { A[k]=R[j]; j++; } else if (R[j]==flag) { A[k]=L[i]; i++; } else if (L[i]>=R[j]) { A[k]=L[i]; i++; } else { A[k]=R[j]; j++; } } } void MERGE_SORT(int A[],int p,int r,int k) { int q=(r+p)/k; if((q-p+1)<k) { return; } else { MERGE_SORT(A,p,q,k); MERGE_SORT(A,q+1,r,k); MERGE(A,p,q,r); } }
注释1:详情见这个是带有插入排序的归并算法(此链接里面的k元素长度值相当于这里的a元素长度值)也就是每个有序数组(共k个)含有有效元素的长度不能大于总元素的开方,这是能够正确进行归并排序的先决条件。这个归并排序,运行时间为O(nlgn),没有到达O(nlgk),实在想不出如何缩短运行时间的方法了。
相关文章推荐
- 两个堆栈实现一个队列和一叠两个队列实现【算法导论课后题】
- 堆实现优先级队列(算法导论第六章)
- “用最小堆将k个已排序链表合并为一个排序链表”(算法导论 练习6.5-9)
- 算法导论 6章堆排序的代码实现和部分课后练习
- 时间复杂度为O(n)的非递归单链表反转【算法导论课后题】
- 算法导论: 第六章 堆排序算法
- c++primer第五版课后练习答案(第六章)
- C Primer Plus 第六章课后习题练习……2015.4.24
- 算法竞赛入门经典:第六章 数据结构基础 6.5小球下落
- 蓝桥杯练习:算法提高 队列操作
- [第三周]第六章课后练习
- 区间图着色问题(算法导论课后题目16.1.3)
- 【算法导论】堆排序和优先级队列
- 算法练习五:用两个栈实现队列
- 算法导论6.5-8堆排序-K路合并
- 「算法导论」:课后习题2.3-7求集合S中是否有两个元素的和为X
- 《算法导论》第六章之堆和优先级队列相关算法C语言实现
- 算法导论 第六章 堆排序