内部排序之插入排序、希尔排序
2014-03-22 20:08
267 查看
排序算法是我们在程序设计过程中需要经常用到的算法,好的排序算法可以有效提高排序效率。
排序算法根据占用内存方式的不同分为两种:内存排序算法和外部排序算法。内部排序算法是指排序工作能够在主存中完成,而不需要访问外存的排序方法。不能只在主存中完成而必须借助外存来完成的排序称为外部排序。
内部排序算法根据排序策略的不同,大体上可以归纳为5类:插入排序,选择排序,交换排序,归并排序和基数排序。其中,插入排序以插入排序和希尔排序这两种方法为主;选择排序则主要包括选择排序和堆排序;交换排序主要包括冒泡法排序和快速排序。
下面将具体介绍5中排序方式的排序思想:插入排序,希尔排序,堆排序,归并排序和快速排序。我们将假设n是所要进行排序的整型元素个数,数据起始位置为0.
1.插入排序
插入排序应该是最简单的一种排序算法,对n个整型元素进行排序,则需要比较n-1趟。对于第p(1 =< p<=n-1)趟比较,,能够保证从位置0到位置p上的元素为已排序状态。
下面通过引入具体的数据来实现该思想:
元素位置 0 1 2 3 4 5
初始 元素 34 8 64 51 32 21
第一趟比较后 8 34 64 51 32 21
第二趟比较后 8 34 64 51 32 21
第三趟比较后 8 34 51 64 32 21
第四趟比较后 8 32 34 51 64 21
第五趟比较后 8 21 32 34 51 64
上面n=6个元素,比较了5趟,第p趟比较都能保证从位置0到位置p上的元素排好序。
插入排序的函数实现如下:
插入排序的算法排序的时间复杂度分析:由于嵌套循环中的每一个都花费n次迭代,当以从大到小的顺序输入时,则得到插入排序时间复杂度的上界为O(N^2);如果输入的数据已经从大到小排好序,内层循环每次都是立即终止,此时就得到插入排序时间复杂度的下界O(N)。插入排序的平均时间复杂度为O(N^2)。
2.希尔排序(shell sort)
希尔排序算法属于插入类排序算法,它通过比较相距一定间隔的元素来工作,各趟比较所用的距离随着算法的进行而减小,直到只比较相邻元素的最后一趟排序为止, 因此 这种排序方法又被人称之为缩小增量排序( diminishing increment sort )。
算法思想:对于n个整型元素(位置从0到n-1),选取一个正整数d1<n,把所有序号相隔d1的数组元素放一组,组内进行直接插入排序,然后取d2<d1,重复上述分组和排序操作,直至di=1,即将所有元素放到一个组内进行插入排序为止。这里就有一个问题:如何选择增量序列di? 增量序列di的一种流行的选择是使用希尔排序的发明人shell 建议的序列,即让d1=n/2,d(i+1)=d(i)/2。
下面将通过引入具体数据来介绍该思想:
元素位置 0 1 2 3 4 5 6 7 8 9
初始元素 48 38 65 97 76 13 27 49 55 4
d1=5排序后 13
27 49
55 4 48
38 65 97 76
d2=2排序后 4
27 13 48 38 55 49 65
97 76
d3=1排序后 4 13 27 38 48 49 55 65 76 97
该方法实质上是分组插入算法,对于上面的10个整型元素,增量序列的取值依次为5,2,1
希尔排序的函数实现:
也可以这样(一个意思):
希尔排序的时间复杂度:使用希尔排序的最坏情形运行时间为O(n^2)。使用Hibbard增量的希尔排序的最坏情形运行时间为O(N^1.5),Hibbard增量排序的增量序列为
{2^k-1,2^(k-1)-1,.....,7,3,1}.Sedgewick提出的几种增量序列,其最坏情形运行时间为O(n^(4/3))。
排序算法根据占用内存方式的不同分为两种:内存排序算法和外部排序算法。内部排序算法是指排序工作能够在主存中完成,而不需要访问外存的排序方法。不能只在主存中完成而必须借助外存来完成的排序称为外部排序。
内部排序算法根据排序策略的不同,大体上可以归纳为5类:插入排序,选择排序,交换排序,归并排序和基数排序。其中,插入排序以插入排序和希尔排序这两种方法为主;选择排序则主要包括选择排序和堆排序;交换排序主要包括冒泡法排序和快速排序。
下面将具体介绍5中排序方式的排序思想:插入排序,希尔排序,堆排序,归并排序和快速排序。我们将假设n是所要进行排序的整型元素个数,数据起始位置为0.
1.插入排序
插入排序应该是最简单的一种排序算法,对n个整型元素进行排序,则需要比较n-1趟。对于第p(1 =< p<=n-1)趟比较,,能够保证从位置0到位置p上的元素为已排序状态。
下面通过引入具体的数据来实现该思想:
元素位置 0 1 2 3 4 5
初始 元素 34 8 64 51 32 21
第一趟比较后 8 34 64 51 32 21
第二趟比较后 8 34 64 51 32 21
第三趟比较后 8 34 51 64 32 21
第四趟比较后 8 32 34 51 64 21
第五趟比较后 8 21 32 34 51 64
上面n=6个元素,比较了5趟,第p趟比较都能保证从位置0到位置p上的元素排好序。
插入排序的函数实现如下:
void InsertSort(int a[],int n)//-------------------------------------1.插入排序 { int j,i,tmp; for(i=1;i<n;i++)//比较n-1趟 { tmp=a[i]; for(j=i;j>=0 && a[j-1] > tmp;j--) a[j]=a[j-1]; a[j]=tmp; } }
插入排序的算法排序的时间复杂度分析:由于嵌套循环中的每一个都花费n次迭代,当以从大到小的顺序输入时,则得到插入排序时间复杂度的上界为O(N^2);如果输入的数据已经从大到小排好序,内层循环每次都是立即终止,此时就得到插入排序时间复杂度的下界O(N)。插入排序的平均时间复杂度为O(N^2)。
2.希尔排序(shell sort)
希尔排序算法属于插入类排序算法,它通过比较相距一定间隔的元素来工作,各趟比较所用的距离随着算法的进行而减小,直到只比较相邻元素的最后一趟排序为止, 因此 这种排序方法又被人称之为缩小增量排序( diminishing increment sort )。
算法思想:对于n个整型元素(位置从0到n-1),选取一个正整数d1<n,把所有序号相隔d1的数组元素放一组,组内进行直接插入排序,然后取d2<d1,重复上述分组和排序操作,直至di=1,即将所有元素放到一个组内进行插入排序为止。这里就有一个问题:如何选择增量序列di? 增量序列di的一种流行的选择是使用希尔排序的发明人shell 建议的序列,即让d1=n/2,d(i+1)=d(i)/2。
下面将通过引入具体数据来介绍该思想:
元素位置 0 1 2 3 4 5 6 7 8 9
初始元素 48 38 65 97 76 13 27 49 55 4
d1=5排序后 13
27 49
55 4 48
38 65 97 76
d2=2排序后 4
27 13 48 38 55 49 65
97 76
d3=1排序后 4 13 27 38 48 49 55 65 76 97
该方法实质上是分组插入算法,对于上面的10个整型元素,增量序列的取值依次为5,2,1
希尔排序的函数实现:
void ShellSort(int a[],int n) { int tmp,i,j,increment; for(increment = n/2;increment > 0;increment /= 2)//增量序列 for(i = increment;i < n;i++) //对每一个步长的增量序列进行类插入排序 { tmp=a[i]; for(j = i;j >=increment;j-=increment) { if(a[j-increment] > tmp) a[j] = a[j-increment];// else { break; } } a[j] = tmp; } }
也可以这样(一个意思):
void ShellSort(int a[],int n) { int tmp,i,j,increment; for(increment = n/2;increment > 0;increment /= 2)//增量序列 for(i = increment;i < n;i++) //对每一个步长的增量序列进行类插入排序 { tmp=a[i]; for(j = i;j >=increment && a[j-increment]>tmp;j-=increment) { a[j] = a[j-increment]; } a[j] = tmp; } }
希尔排序的时间复杂度:使用希尔排序的最坏情形运行时间为O(n^2)。使用Hibbard增量的希尔排序的最坏情形运行时间为O(N^1.5),Hibbard增量排序的增量序列为
{2^k-1,2^(k-1)-1,.....,7,3,1}.Sedgewick提出的几种增量序列,其最坏情形运行时间为O(n^(4/3))。
相关文章推荐
- linux系统编程之进程(五):exec系列函数(execl,execlp,execle,execv,execvp)使用
- 杭电2549 壮志难酬
- (SSH)java.lang.NullPointerException解决方案
- JSTL EL表达式
- C 语言编写 Linux 中的 ls 命令
- Hibernate中get和load的区别
- 三角形类2
- John's trip
- Hibernate 学习---建立第一个基本的hibaernate运行程序
- Spring的jdbcTemplate使用
- android paint类(绘图类) 方法全解析
- vijos 1218 数字游戏(环形dp)
- JSOUP初探
- Chosen—jquery选择框插件
- JDBC 增删改查
- HDU 1856 More is better
- java中的递归
- 样本方差的无偏估计与(n-1)的由来
- linux系统编程之信号(四):alarm和可重入函数
- mac 下安装配置 MySQL + Apache +phpMyAdmin