内部排序之插入排序、希尔排序

        排序算法是我们在程序设计过程中需要经常用到的算法,好的排序算法可以有效提高排序效率。

        排序算法根据占用内存方式的不同分为两种:内存排序算法和外部排序算法。内部排序算法是指排序工作能够在主存中完成,而不需要访问外存的排序方法。不能只在主存中完成而必须借助外存来完成的排序称为外部排序。

        内部排序算法根据排序策略的不同,大体上可以归纳为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))。


     

 

       

       

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值