周五学习的线性时间选择,以寻找第k小的数字为入口。
首先是对一组乱序的数字进行排序,乱序的数字由之前的随机数函数产生。
排序采用快速排序。算法描述在下面代码中给出
/* Name: Quicksort Copyright: bg2bkk Author: bg2bkk Date: 12/09/10 01:51 Description: name 快速排序(采用递归方式) input:随机的数组a[n] output :经过排序好的数组 算法主体: QuickSort(ElemType a[],p,r) { if(p<r) then i=Partition(a[],p,r) QuickSort(a,p,i-1); QuickSort(a,i+1,r); } 采用分治方法,将数组一分为二,以数组的某一个元素为基准,左边的元素都 不大于它,右边的数都不小于它。然后再次对双方进行再次分组。直至分到最 小单位-- 单个元素。这是分治的最佳体现 name 划分 描述:对一定范围内的数字进行划分,使其以某个元素为基准左边的元素都不 大于它,右边的数都不小于它。 算法主体 Partition(ElemType a[],int p,int r) { i=p;j=r+1; //从两边开始,对整个数组进行划分 ElemType x=a[p] //以第一个元素a[p]作为基准 while(1) //直至划分完毕 { while(a[++i]<x&&i<r); //找到左边第一个大于基准(就是a[p])的元素a[i] while(a[--j]>x); //找到右边第一个小于 基准的元素a[j] if(i>=j) break; //若未遍历完,继续,直至i j相遇,说明遍历结束 swap(a,i,j); //将两个元素进行互换这样就保证左边都小于a[p], //右边大于a[p] } a[p]=a[j]; a[j]=x; return j; } */ #include<iostream> #define ElemType int using namespace std; void swap(ElemType *a,int i,int j) { ElemType t; t=a[i]; a[i]=a[j]; a[j]=t; } int Partition(ElemType *a,int p,int r) { int i=p,j=r+1; ElemType x=a[p]; while(1) { while(a[++i]<x&&i<r); while(a[--j]>x); if(i>=j) break; swap(a,i,j); } a[p]=a[j]; a[j]=x; return j; } void quicksort(ElemType *a,int p,int r) { if(p<r) { int q=Partition(a,p,r); quicksort(a,p,q-1); quicksort(a,q+1,r); } } int main() { ElemType a[]={81509631,17360533,15539299,64493064,64645058,87825487, 33900461,4945505,15941463,71719600,33547516,7519808, 26594898,29884844,27119583,81863654,59673947,84147293, 9059351,7602292,83556926,37027377,75613515,93681811, 7952779,60044456,98264756,67951181,26925847,22994199, 31900994,18462642,9142808,36512424,8589397,65003012, 50519485,63287896,27573828,82252268,63300436,87128823, 48058746,8633666,55332881,61522155,88747604,29979896, 22489406,43687198,2492180,91630320,16002389,75781403, 57871937,8803618,89285976,11751109,40281540,22122151, 13194234,18823824,70845645,55985568,10967476,92437158, 89459068,17676128,66174144,39733764,17145305,75974958, 11895329,59458458,14862124,20811108,9863145,51935822, 33956581,17530466,15311298,8616585,22966662,65420236, 44315494,76347881,93961092,78556039,3529430,73342285, 38929178,36935665,39496167,18536269,71760501,83187750, 67284000,91035727,66780185,94022027,12416029,35114323, 59427850,31203431,10652528,35584440,28212772,84184997, 59600395,4622020,32839956,58298468,400951,94479104,77962861, 82427078,78885887,38543465,94902132,85359893,26182181, 1299345,25702676,51437241,29489005,52205900,58991659,95743251, 22271901,2074436,40743771,46382245,53875748,48138885,19686345, 12289464,44726496,26239089,84581121,64361813,82495717,59275005, 19287553,57530620,31526077,25269250,4957225,21500576,38595138, 70705661,35608130,47769609,24306886,5200032,68301732,40811553, 43024796,24475167,48355438,25501447,28554316,31471507,47641698, 63229167,63685827,96720378,54736518,19690144,7705313,5972805, 5902292,18461652,20283817,74773721,63408346,1334492,15542468, 16486207,39129819,63788537,6178430,17315589,27070237,20483236, 1082584,96921242,25938585,71799656,31463668,93111205,91860702, 23510866,85667996,76688782,4609454,79901560,61821340,79590883, 57517711,62374479}; for(int i=0;i<100;i++) cout<<a[i]<<" "; cout<<endl; quicksort(a,0,99); for(int i=0;i<100;i++) cout<<a[i]<<" "; cout<<endl; getchar(); }
以上为QuickSort算法。
一下为选择第k小的元素,先给出代码吧
/* Name: 寻找第k大的数字 Copyright: 电子工业出版社《计算机算法设计与分析 第三版》p25 线性时间选择 Author: bg2bkk Date: 12/09/10 02:20 Description: */ #include<iostream> #define Random() srand((unsigned)time(NULL)) #define ElemType int using namespace std; void swap(ElemType *a,int i,int j) { ElemType t; t=a[i]; a[i]=a[j]; a[j]=t; } int Partition(ElemType *a,int p,int r) { int i=p; int j=r+1; ElemType x=a[p]; while(1) { while(a[++i]<x&&i<r); while(a[--j]>x); if(i>=j) break; swap(a,j,i); } a[p]=a[j]; a[j]=x; return j; } int RandomPartition(ElemType *a,int p,int r) { Random(); int i=p+rand()%(r-p); swap(a,i,p); return Partition(a,p,r); } ElemType RandomizedSelect(ElemType *a,int p,int r,int k) { if(p==r) return a[p]; int i=RandomPartition(a,p,r); int j=i-p+1; if(k<=j) return RandomizedSelect(a,p,i,k); else return RandomizedSelect(a,i+1,r,k-j); } int main() { ElemType a[]={81509631,17360533,15539299,64493064,64645058,87825487, 33900461,4945505,15941463,71719600,33547516,7519808, 26594898,29884844,27119583,81863654,59673947,84147293, 9059351,7602292,83556926,37027377,75613515,93681811, 7952779,60044456,98264756,67951181,26925847,22994199, 31900994,18462642,9142808,36512424,8589397,65003012, 50519485,63287896,27573828,82252268,63300436,87128823, 48058746,8633666,55332881,61522155,88747604,29979896, 22489406,43687198,2492180,91630320,16002389,75781403, 57871937,8803618,89285976,11751109,40281540,22122151, 13194234,18823824,70845645,55985568,10967476,92437158, 89459068,17676128,66174144,39733764,17145305,75974958, 11895329,59458458,14862124,20811108,9863145,51935822, 33956581,17530466,15311298,8616585,22966662,65420236, 44315494,76347881,93961092,78556039,3529430,73342285, 38929178,36935665,39496167,18536269,71760501,83187750, 67284000,91035727,66780185,94022027,12416029,35114323, 59427850,31203431,10652528,35584440,28212772,84184997, 59600395,4622020,32839956,58298468,400951,94479104,77962861, 82427078,78885887,38543465,94902132,85359893,26182181, 1299345,25702676,51437241,29489005,52205900,58991659,95743251, 22271901,2074436,40743771,46382245,53875748,48138885,19686345, 12289464,44726496,26239089,84581121,64361813,82495717,59275005, 19287553,57530620,31526077,25269250,4957225,21500576,38595138, 70705661,35608130,47769609,24306886,5200032,68301732,40811553, 43024796,24475167,48355438,25501447,28554316,31471507,47641698, 63229167,63685827,96720378,54736518,19690144,7705313,5972805, 5902292,18461652,20283817,74773721,63408346,1334492,15542468, 16486207,39129819,63788537,6178430,17315589,27070237,20483236, 1082584,96921242,25938585,71799656,31463668,93111205,91860702, 23510866,85667996,76688782,4609454,79901560,61821340,79590883, 57517711,62374479}; for(int i=0;i<100;i++) { cout<<a[i]<<" "; if((i+1)%10==0) cout<<endl; } cout<<endl; cout<<endl; int n; scanf("%d",&n); cout<<RandomizedSelect(a,0,99,n); getchar(); getchar(); }
/* Name: 寻找第k小的数字,经过优化的算法 Copyright: 电子工业出版社《计算机算法设计与分析 第三版》p25 线性时间选择 Author: bg2bkk Date: 12/09/10 13:32 Description: */ #include<iostream> #define Random() srand((unsigned)time(NULL)) #define ElemType int using namespace std; void swap(ElemType *a,int i,int j) { ElemType t; t=a[i]; a[i]=a[j]; a[j]=t; } int Partition(ElemType *a,int p,int r) { int i=p,j=r+1; ElemType x=a[p]; while(1) { while(a[++i]<x&&i<r); while(a[--j]>x); if(i>=j) break; swap(a,i,j); } a[p]=a[j]; a[j]=x; return j; } int Partition(ElemType *a,int p,int r,ElemType x) { int i=p,j=r+1; //ElemType x=a[p]; while(1) { while(a[++i]<x&&i<r); while(a[--j]>x); if(i>=j) break; swap(a,i,j); } a[p]=a[j]; a[j]=x; return j; } void quicksort(ElemType *a,int p,int r) { if(p<r) { int q=Partition(a,p,r); quicksort(a,p,q-1); quicksort(a,q+1,r); } } ElemType Select(ElemType *a,int p,int r,int k) { if(r-p<75) { quicksort(a,p,r); return a[p+k-1]; } for(int i=0;i<=(r-p-4)/5;i++) { quicksort(a,p+5*i,p+5*i+4); swap(a,p+i,p+5*i+2); } ElemType x=Select(a,p,p+(r-p-4)/5,(r-p-4)/10); int i=Partition(a,p,r,x); int j=i-p+1; if(k<=j) return Select(a,p,i,k); else return Select(a,i+1,r,k-j); } int main() { ElemType a[]={81509631,17360533,15539299,64493064,64645058,87825487, 33900461,4945505,15941463,71719600,33547516,7519808, 26594898,29884844,27119583,81863654,59673947,84147293, 9059351,7602292,83556926,37027377,75613515,93681811, 7952779,60044456,98264756,67951181,26925847,22994199, 31900994,18462642,9142808,36512424,8589397,65003012, 50519485,63287896,27573828,82252268,63300436,87128823, 48058746,8633666,55332881,61522155,88747604,29979896, 22489406,43687198,2492180,91630320,16002389,75781403, 57871937,8803618,89285976,11751109,40281540,22122151, 13194234,18823824,70845645,55985568,10967476,92437158, 89459068,17676128,66174144,39733764,17145305,75974958, 11895329,59458458,14862124,20811108,9863145,51935822, 33956581,17530466,15311298,8616585,22966662,65420236, 44315494,76347881,93961092,78556039,3529430,73342285, 38929178,36935665,39496167,18536269,71760501,83187750, 67284000,91035727,66780185,94022027,12416029,35114323, 59427850,31203431,10652528,35584440,28212772,84184997, 59600395,4622020,32839956,58298468,400951,94479104,77962861, 82427078,78885887,38543465,94902132,85359893,26182181, 1299345,25702676,51437241,29489005,52205900,58991659,95743251, 22271901,2074436,40743771,46382245,53875748,48138885,19686345, 12289464,44726496,26239089,84581121,64361813,82495717,59275005, 19287553,57530620,31526077,25269250,4957225,21500576,38595138, 70705661,35608130,47769609,24306886,5200032,68301732,40811553, 43024796,24475167,48355438,25501447,28554316,31471507,47641698, 63229167,63685827,96720378,54736518,19690144,7705313,5972805, 5902292,18461652,20283817,74773721,63408346,1334492,15542468, 16486207,39129819,63788537,6178430,17315589,27070237,20483236, 1082584,96921242,25938585,71799656,31463668,93111205,91860702, 23510866,85667996,76688782,4609454,79901560,61821340,79590883, 57517711,62374479}; for(int i=0;i<100;i++) { cout<<a[i]<<" "; if((i+1)%10==0) cout<<endl; } cout<<endl; cout<<endl; int n; scanf("%d",&n); cout<<Select(a,0,99,n); getchar(); getchar(); }