首页 > 代码库 > 希尔排序

希尔排序

希尔排序(Shell Sort)插入排序的一种。是针对直接插入排序算法的改进。该方法又称缩小增量排序,因DL.Shell于1959年提出而得名。先取一个小于n的整数d1作为第一个增量,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序;然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量dt=1(dt<dt-l<…<d2<d1),即所有记录放在同一组中进行直接插入排序为止(即最后一趟为直接插入排序)。

希尔排序是基于插入排序的以下两点性质而提出改进方法的:
1.插入排序在对几乎已经排好序的数据操作时, 效率高, 即可以达到线性排序的效率

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

算法分析
1.增量序列的选择

     Shell排序的执行时间依赖于增量序列。
     好的增量序列的共同特征:
  ① 最后一个增量必须为1;
  ② 应该尽量避免序列中的值(尤其是相邻的值)互为倍数的情况。
     有人通过大量的实验,给出了目前较好的结果:当n较大时,比较和移动的次数约在nl.25到1.6n1.25之间。
2.Shell排序的时间性能优于直接插入排序
     希尔排序的时间性能优于直接插入排序的原因:
  ①当文件初态基本有序时直接插入排序所需的比较和移动次数均较少。
  ②在希尔排序开始时增量较大,分组较多,每组的记录数目少,故各组内直接插入较快,后来增量di逐渐缩小,分组数逐渐减少,而各组的记录数目逐渐增多,但由于已经按di-1作为距离排过序,使文件较接近于有序状态,所以新的一趟排序过程也较快。
     因此,希尔排序在效率上较直接插人排序有较大的改进。
3.稳定性
     希尔排序是不稳定的。      


实现:

//ader为增量
void ShellInsert(int arr[],int len,int ader)
{
	if(arr == NULL || len <= 0 || ader <= 0)
	{
		return;
	}
	int i,j,temp;
	for(i = ader; i < len; i++)
	{
		if(arr[i-ader] > arr[i]) 
		{
			temp = arr[i];
			for(j = i-ader; j>=0 && temp < arr[j]; j-=ader)
			{
				arr[j+ader] = arr[j];
			}
			arr[j+ader] = temp;
		}
	}
}
//dlta为增量序列,t为增量序列的长度
void ShellSort(int arr[],int len,int dlta[],int t)
{
	for(int i = 0; i < t; i++)
	{
		ShellInsert(arr,len,dlta[i]);//使用每个增量,进行直接插入排序
	}
}

测试:

/****************************************
希尔排序
by Rowandjj
2014/7/19
****************************************/
#include<iostream>
using namespace std;
//ader为增量
void ShellInsert(int arr[],int len,int ader)
{
	if(arr == NULL || len <= 0 || ader <= 0)
	{
		return;
	}
	int i,j,temp;
	for(i = ader; i < len; i++)
	{
		if(arr[i-ader] > arr[i]) 
		{
			temp = arr[i];
			for(j = i-ader; j>=0 && temp < arr[j]; j-=ader)
			{
				arr[j+ader] = arr[j];
			}
			arr[j+ader] = temp;
		}
	}
}
//dlta为增量序列,t为增量序列的长度
void ShellSort(int arr[],int len,int dlta[],int t)
{
	for(int i = 0; i < t; i++)
	{
		ShellInsert(arr,len,dlta[i]);//使用每个增量,进行直接插入排序
	}
}
int main()
{
	int i;
	int arr[] = {9,7,5,3,1,6,11,8,4};
	int dlta[] = {5,3,1};
	ShellSort(arr,9,dlta,3);
	for(i = 0; i < 9; i++)
	{
		cout<<arr[i]<<" ";
	}
	cout<<endl;
	return 0;
}

结果: