算法导论_第八章_线性时间排序
2016-06-29 17:12
567 查看
算法导论_第八章_线性时间排序
排序算法的下界
决策树模型
决策树是一颗完全二叉树
决策树的每个节点代表需要比较的两个数,叶节点为一个数的排序。所以任何正确的排
序,n个元
素的n!个排列情况都应该出现在叶节点上。
比较排序的最坏情况出现在比较次数为决策树的高度,而决策数的高度
h<=lg(n!)=Ω(n*lg(n))
堆排序和归并排序都是渐进最优的比较排序算法
其运行时间上界为O(n*lg(n))
计数排序:
基本思想:
对于每一个输入的元素x,确定小于x的元素个数。利用这一信息可以直接把x放到它在输出
数组中的位置上。
下面来看代码:
据计算其时间复杂度为Θ(n)
计数排序不涉及到比较,所以其脱离比较模型,时间复杂度可以降低很多,再者其具有
稳定性,对于附带卫星数据来说,比较重要。
不过当k非常大时,可能导致内存空间利用过多。
基数排序:
排序思想:
假定要对一个有10位的十进制的数排序,那么就从最低有效位开始进行排序,就是先对个位数进行排序,
然后十位,百位……直到排序完成,在排序过程中卫星数据顺序不变,所以需要稳定的排序算法。
这里可以采用基数排序
下面上具体代码:
其利用了计数排序,对n个d位数来说
其时间复杂度为:Θ(d*(n+k))
d为常数时且k=O(n),基数排序具有线性的时间代价
由于其不是原址排序,所以其会耗费大量内存空间,当内存非常珍贵的情况下,利用快排
桶排序:
桶排序假设输入的数据服从均匀分布,平均情况下,其时间代价为O(n)
桶排序将[0,1)区间划分为n个相同大小的子区间上,或称为桶,然后将n个输入数分别放到各个桶中,先对
桶中的数进行排序,然后遍历每个桶,按照次序把各个桶中的元素列出来。
下面看具体代码:
桶排序效率分析:
桶排序的时间代价为
T(n)=Θ(n)+sum(O(n[i]^2))
最后求得其时间复杂度为:Θ(n)
即使输入数据不服从平均分布桶排序也仍然可以在线性时间内完成。只要输入数据满足所有桶的大小的平
方和与总的元素呈线性关系。
排序算法的下界
决策树模型
决策树是一颗完全二叉树
决策树的每个节点代表需要比较的两个数,叶节点为一个数的排序。所以任何正确的排
序,n个元
素的n!个排列情况都应该出现在叶节点上。
比较排序的最坏情况出现在比较次数为决策树的高度,而决策数的高度
h<=lg(n!)=Ω(n*lg(n))
堆排序和归并排序都是渐进最优的比较排序算法
其运行时间上界为O(n*lg(n))
计数排序:
基本思想:
对于每一个输入的元素x,确定小于x的元素个数。利用这一信息可以直接把x放到它在输出
数组中的位置上。
下面来看代码:
/************************************************************************* > File Name: counting_sort.cpp > Author:chudongfang > Mail:1149669942@qq.com > Created Time: 2016年06月29日 星期三 08时42分35秒 ************************************************************************/ #include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<stdlib.h> #include <algorithm> #define INF 0x3f3f3f3f using namespace std; typedef long long ll; void counting_sort(int a[],int b[],int n,int k); int main(int argc,char *argv[]) { int a[100],b[100]; int n; int max=-INF; printf("please input the number of array:"); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); if(max<a[i]) max=a[i];//确定输入元素的最大值,便于开辟c数组 } counting_sort(a,b,n,max); for(int i=1;i<=n;i++) printf("%d ",b[i]); return 0; } //a数组表示要排序的数组, //b表示排序过后的数组, //c表示a数组元素在b数组中的位置。 void counting_sort(int a[],int b[],int n,int k) { int c[1000]; for(int i=0;i<=k;i++) c[i]=0; for(int i=1;i<=n;i++) c[a[i]]++;//初始化为1代表有1个元素与其相等,为其本身 /*******important**************/ for(int i=1;i<=k;i++)//确定比其小或等于的元素的个数 c[i]+=c[i-1]; for(int j=n;j>=1;j--) { b[c[a[j]]]=a[j];//确定位置 c[a[j]]--;//若有重复,则位置减1 //在这里,其保证了如果多个元素相同,其在b数组中的顺序与其 //在a数组中的顺序相同,就保证了其稳定性。 } /*****************************/ }
据计算其时间复杂度为Θ(n)
计数排序不涉及到比较,所以其脱离比较模型,时间复杂度可以降低很多,再者其具有
稳定性,对于附带卫星数据来说,比较重要。
不过当k非常大时,可能导致内存空间利用过多。
基数排序:
排序思想:
假定要对一个有10位的十进制的数排序,那么就从最低有效位开始进行排序,就是先对个位数进行排序,
然后十位,百位……直到排序完成,在排序过程中卫星数据顺序不变,所以需要稳定的排序算法。
这里可以采用基数排序
下面上具体代码:
/************************************************************************* > File Name: radix_sort.cpp > Author:chudongfang > Mail:1149669942@qq.com > Created Time: 2016年06月29日 星期三 09时46分44秒 ************************************************************************/ #include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<stdlib.h> #include <algorithm> #define INF 0x3f3f3f3f using namespace std; typedef long long ll; typedef struct node { int ge; int shi; int bai; }NODE; void counting_sort_ge(NODE a[],NODE b[],int n,int k); void counting_sort_shi(NODE a[],NODE b[],int n,int k); void counting_sort_bai(NODE a[],NODE b[],int n,int k); int main(int argc,char *argv[]) { NODE a[100]; NODE b[100]; a[1].ge=1; a[1].shi=2; a[1].bai=3; a[2].ge=2; a[2].shi=2; a[2].bai=2; a[3].ge=7; a[3].shi=2; a[3].bai=3; a[4].ge=3; a[4].shi=1; a[4].bai=2; a[5].ge=5; a[5].shi=2; a[5].bai=3; int n=5,d=3; int max_ge=7; int max_shi=2; int max_bai=3; counting_sort_ge(a,b,n,max_ge); counting_sort_shi(b,a,n,max_shi); counting_sort_bai(a,b,n,max_bai); for (int i = 1; i <=5; ++i) { printf("%d%d%d\n",b[i].bai,b[i].shi,b[i].ge); } return 0; } void counting_sort_ge(NODE a[],NODE b[],int n,int k) { int c[1000]; for(int i=0;i<=k;i++) c[i]=0; for(int i=1;i<=n;i++) c[a[i].ge]++;//初始化为1代表有1个元素与其相等,为其本身 /*******important**************/ for(int i=1;i<=k;i++)//确定比其小或等于的元素的个数 c[i]+=c[i-1]; for(int j=n;j>=1;j--) { b[c[a[j].ge]]=a[j];//确定位置 c[a[j].ge]--;//若有重复,则位置减1 //在这里,其保证了如果多个元素相同,其在b数组中的顺序与其 //在a数组中的顺序相同,就保证了其稳定性。 } /*****************************/ } void counting_sort_shi(NODE a[],NODE b[],int n,int k) { int c[1000]; for(int i=0;i<=k;i++) c[i]=0; for(int i=1;i<=n;i++) c[a[i].shi]++;//初始化为1代表有1个元素与其相等,为其本身 /*******important**************/ for(int i=1;i<=k;i++)//确定比其小或等于的元素的个数 c[i]+=c[i-1]; for(int j=n;j>=1;j--) { b[c[a[j].shi]]=a[j];//确定位置 c[a[j].shi]--;//若有重复,则位置减1 //在这里,其保证了如果多个元素相同,其在b数组中的顺序与其 //在a数组中的顺序相同,就保证了其稳定性。 } /*****************************/ } void counting_sort_bai(NODE a[],NODE b[],int n,int k) { int c[1000]; for(int i=0;i<=k;i++) c[i]=0; for(int i=1;i<=n;i++) c[a[i].bai]++;//初始化为1代表有1个元素与其相等,为其本身 /*******important**************/ for(int i=1;i<=k;i++)//确定比其小或等于的元素的个数 c[i]+=c[i-1]; for(int j=n;j>=1;j--) { b[c[a[j].bai]]=a[j];//确定位置 c[a[j].bai]--;//若有重复,则位置减1 //在这里,其保证了如果多个元素相同,其在b数组中的顺序与其 //在a数组中的顺序相同,就保证了其稳定性。 } /*****************************/ }
其利用了计数排序,对n个d位数来说
其时间复杂度为:Θ(d*(n+k))
d为常数时且k=O(n),基数排序具有线性的时间代价
由于其不是原址排序,所以其会耗费大量内存空间,当内存非常珍贵的情况下,利用快排
桶排序:
桶排序假设输入的数据服从均匀分布,平均情况下,其时间代价为O(n)
桶排序将[0,1)区间划分为n个相同大小的子区间上,或称为桶,然后将n个输入数分别放到各个桶中,先对
桶中的数进行排序,然后遍历每个桶,按照次序把各个桶中的元素列出来。
下面看具体代码:
/************************************************************************* > File Name: bucket_sort.cpp > Author:chudongfang > Mail:1149669942@qq.com > Created Time: 2016年06月29日 星期三 10时50分26秒 ************************************************************************/ #include<iostream> #include<stdio.h> #include<string.h> #include<math.h> #include<stdlib.h> #include <algorithm> #define INF 0x3f3f3f3f using namespace std; typedef long long ll; void bucket_sort(float a[],float b[][100],int num[],int n,float max); int main(int argc,char *argv[]) { float a[100];//要排序的数组 float b[100][100];//桶 int num[100];//桶内的元素 int n; float max=-INF; memset(num,0,sizeof(num));//赋值清零 scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%f",&a[i]); if(a[i]>max) max=a[i];//找到最大值 } bucket_sort(a,b,num,n,max);//桶排序 for(int i=1;i<=n;i++) { for(int j=1;j<=num[i];j++) printf("%g ",b[i][j]); } return 0; } void bucket_sort(float a[],float b[][100],int num[],int n,float max) { int i,j,k; for(i=1;i<=n;i++) { j=(int)(a[i]/max*n);//找到其应该放入桶的下标 if(!j) j++; //如果为0,则变为1 num[j]++; //计数器加1 /*************插入排序_部分功能********************/ for(k=num[j];k>1&&b[j][k-1]>a[i];k--) b[j][k]=b[j][k-1]; b[j][k]=a[i]; } }
桶排序效率分析:
桶排序的时间代价为
T(n)=Θ(n)+sum(O(n[i]^2))
最后求得其时间复杂度为:Θ(n)
即使输入数据不服从平均分布桶排序也仍然可以在线性时间内完成。只要输入数据满足所有桶的大小的平
方和与总的元素呈线性关系。
相关文章推荐
- Android项目研发之多分辨率适配
- php 无法接收post数据
- vs打开项目,创建虚拟目录,提示权限不足无法写入配置文件
- 分组求最大值,最小值 使用开窗函数经验总结
- ps -C
- springmvc整合mybatis错误:java.lang.AbstractMethodError,sqlSessionFactoryBeanName造成tomcat启动错误
- 【那些工作中学到的小技巧】打印进程名和线程名
- LeetCode - 274. H-Index
- MVC 中获取Json数据
- [Leetcode]328. Odd Even Linked List
- HDU2018--母牛的故事
- C语言版iso8583报文拆包组包代码
- Eclipse调试:F5、F6、F7、F8
- bitmap 和 drawable 转化
- Java Web总结(二)-- 上传和下载
- OpenCV 3.0中IplImage* 转cv::Mat
- Java集合源码分析(一)
- spring定时器配置为整点执行
- 医学扫盲 —— 身体篇
- PXE实现批量安装部署(win与linux系统)