八大排序———希尔排序

  希尔排序(Shell's sort)是插入排序的一种 又称为“缩小增量排序”(Diminishing Increment Sort),是直接插入排序算法的一种更高效的改进版本。希尔排序是不稳定的排序算法。

  希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量的逐渐减少,每组包含的关键字越来越多,当增量减少至1时,整个文件恰被分为一组,算法终止。

    希尔排序是基于插入排序的一下两点性质而提出改进方法的:

1.插入排序在对几乎已经排好序的数据操作时,效率高,既可以达到线性排序的效率。

2.但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位。

一:基本思想

  先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组中进行直接插入排序;然后取第二个增量d2<d1重复上述的分组和排序,直至所取的增量d = 1,即所有的记录放在同一组中进行直接插入排序为止。

    实质:分组插入方法

  比较相隔较远距离(称为增量)的数,使得移动时能够跨越多个元素,则进行一次比较就可能消除多个元素的交换。

一般的初次取序列的一半为增量,以后每次减半,直到增量为1。

 二:演示过程 

三:代码解析

#include<iostream>
using namespace std;

template<typename T>
void shellinsert(T arr[],int len,int grp)//O(n)
{
		int i = grp;
		int j = 0;
		T tmp = T();
		for(i=grp;i<len;++i)
		{
				tmp = arr[i];
				for(j = i-grp;j>=0;j-=grp)
				{
						if(arr[j]>tmp)
						{
								arr[j+grp] = arr[j];
						}
						else
								break;
				}
				arr[j+grp] = tmp; 
		}
}
template<typename T>
void shell(T arr[],int len)
{
		for(int div = len/2;div>0;div/=2)//时间复杂度为O(log n)
		shellinsert(arr,len,div);

}

int main()
{
		int arr[] = {15,48,67,9,45,13,16,9,99,13};
		int len = sizeof(arr)/sizeof(arr[0]);
		shell1(arr,len);
		for(int i= 0;i<len;++i)
		{
				cout<<arr[i]<<" ";
		}
		cout<<endl;
		return 0;
}

四:稳定性分析

  由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元素的相对顺序,但在不同的插入排序过程中,相同的元素可能在各自插入排序中移动,最后其稳定性就会被打乱,所以shell排序是不稳定的。

五:时间复杂度

  算法的平均复杂度为 O(n^1.3),算法的最坏的时间复杂度为O(n^2),最好的时间复杂度为O(n),空间复杂度为O(1)。

六:算法分析

  不需要大量的辅助空间,希尔排序是基于插入排序的一种算法,在此算法之上增加了新的特性,提高了效率。希尔排序的时间复杂度与增量序列的选取有关,例如希尔增量的时间复杂度为O(n^2),而Hibbard增量的希尔排序的时间复杂度为O(n^1.5),当数据量相当大的时间,其算法的效率不如快排快,因此中等大小的数据量适用于希尔排序,希尔排序在最坏和平均的情况下执行效率差不多,而快速排序的最坏和平均的情况下其相差比较大,所以,几乎任何排序工作在开始时都可以用希尔排序,如果在实际中,其速度不能满足我们的要求我们在使用快排。

shell算法的性能与所选取的分组长度序列有关。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值