递归归并排序和非递归归并排序(自然分组)
2016-03-21 19:02
239 查看
递归合并排序
算法思想:将待排序的集合一分为二,直到排序集合就剩下一个元素为止,然后不断的合并两个排好序的数组。#include<iostream> #include<cstdlib> #include<random> #include<sys/timeb.h> #include<ctime> #define N 200000 using namespace std; int merge(int a[],int low,int mid,int high){ //对排好序的两个分组进行合并 int i=low,j=mid+1,p=0; int *temp=(int *)malloc(sizeof(int)); //开辟临时数组存合并后的元素。 if(temp == NULL){ return -1; } while(i<=mid && j<=high){ temp[p++]=((a[i]<=a[j])?a[i++]:a[j++]); } while(i<=mid){ temp[p++]=a[i++]; } while(j<=high){ temp[p++]=a[j++]; } for(p=0,i=low;i<=high;i++,p++){ a[i]=temp[p]; } free(temp); } void mergeSort(int a[],int low,int high) { int mid=(low + high)/2; if(low < high) //说明此时只剩下一个元素,不用再分。 { mergeSort(a,low,mid); //对左边的元素依然进行分, mergeSort(a,mid+1,high); merge(a,low,mid,high); } } int main(int argc,char *argv[]) { int a ; uniform_int_distribution<unsigned> u(0,300000); //生成随机数(0,300000)之间的数. default_random_engine e; for(size_t i=0;i<N;i++){ //生成20000的随机数进行测试。 a[i]=u(e); } mergeSort(a,0,N-1); return 0; }
非递归归并排序—自然分组.
算法思想:遍历把一个无序的集合,把局部有序的元素划分为一组,两两进行合并,一次合并完毕,再次进行自然分组,然后再两两合并,直到最后一次合并后只剩下一个分组,至此,这个无序的集合就成为有序的集合了。#include<iostream> #include<vector> #include<random> #include<sys/timeb.h> #include<ctime> #define N 200000 using namespace std; int fenzu(int (&a) ,int (&b) ) //自然分组,记录每个分组的起始位置的下标。 { int temp=a[0]; int j=0; int i; b[j++]=0; //第一个分组一定是从0号下标结束。 for(i=1;i<N;i++){ if(temp <= a[i]){ temp=a[i]; }else{ b[j++]=i; temp=a[i]; } } b[j++]=N; //把数组的最后一个元素下标的下一个位置存下来,方便后面的判断结束条件。 return j; } void merge(int (&a) ,int left,int mid,int right) { int i=left,j=mid+1,k=left; int d ; while(i<=mid && j<=right){ if(a[i] < a[j]){ d[k++]=a[i++]; }else{ d[k++]=a[j++]; } } if(i!=mid+1){ //说明左边的元素还有,直接加在临时数组d中。 for(int t=i;t<=mid;t++){ d[k++]=a[t]; } } if(j!=right+1){ for(int t=j;t<=right;t++){ //说明右边的元素还有,直接加在临时数组d中。 d[k++]=a[t]; } } for(int i=left;i<=right;i++){ //把此次进行合并后的元素拷贝到原数组,没有参与合并的数组元素不变.为了进行下一次自然分组。 a[i]=d[i]; } //for(int i=0;i<N;i++){ // cout << a[i]<<" "; //} //cout <<endl; } void mergeSort(int (&a) ,int (&b) ) { int length=fenzu(a,b),i=0; //cout << "length:"<<length<< endl; while(length!=2){ for(int i=0;i<length-2;i+=2){ //注意,这里的i<length-2,因为虾下面有b[i+2],不然数组会越界. merge(a,b[i],b[i+1]-1,b[i+2]-1); } length=fenzu(a,b); //一次合并完成,重新进行自然分组. } } int main(int argc,char *argv[]) { struct timeb startTime,endTime; ftime(&startTime); int a ; uniform_int_distribution<unsigned> u(0,300000); //生成随机数(0,300000); default_random_engine e; for(size_t i=0;i<N;i++){ a[i]=u(e); } int b ; mergeSort(a,b); /* for(int i=0;i<N;i++){ //这是输出. cout<<a[i]<< " "; } cout << endl;*/ ftime(&endTime); cout <<(endTime.time-startTime.time)*1000+(endTime.millitm-startTime.millitm)<<"毫秒"<<endl; return 0; }
相关文章推荐
- 第二讲--SQL语句执行过程
- POJ-1004
- Zepto事件模块源码分析
- 单元测试
- BZOJ2705Longge的问题
- 在codeblock里创建一个OpenGL项目
- DICOM图像格式
- 58.respondsToSelector和conformsToProtocol方法的应用
- Easy Image 使用总结
- Notification通知类
- div的onblur事件
- 信号量进程同步,王明学learn
- 段焱--web前端开发须知规范
- 在Bootstrap的Modal form里面添加PartialView
- 求数组的最大K个数
- 使用Visual Studio 2013进行单元测试的过程与感想
- 活动的创建
- 将两个线性链表归并为一个有序链表
- Android开发的ANR和Force Close
- nginx证书填写路径报错:library:fopen:Unknown error:fopen