数据结构:常见的排序算法(四):希尔排序(C++实现)

数据结构:常见的排序算法(四)-希尔排序

插入排序:

1.思想:每步将一个待排序的记录,按其顺序码大小插入到前面已经排序的字序列的合适位置,直到全部插入排序完为止。
2.关键问题:在前面已经排好序的序列中找到合适的插入位置。
方法: 分为 直接插入排序二分插入排序希尔排序

希尔排序

1959年Shell发明,第一个突破O(n2)的排序算法,是简单插入排序的改进版。它与插入排序的不同之处在于,它会优先比较距离较远的元素。希尔排序又叫缩小增量排序

1.基本思想:

希尔排序又叫“缩小增量排序”,先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行直接插入排序,然后取第二个增量d2。其是插入排序改良的算法,希尔排序步长从大到小调整,第一次循环后面元素逐个和前面元素按间隔步长进行比较并交换,直至步长为1,步长选择是关键。

算发描述:

先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,具体算法描述:

  • 选择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;
  • 按增量序列个数k,对序列进行k 趟排序;
  • 每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。

2.实例

给数组a[11]={70,30,40,10,80,20,90,100,75,60,45}通过希尔排序进行排序

img
图片来源:https://www.cnblogs.com/zwtgyh/p/10631760.html

#include<iostream>
using namespace std;
//希尔排序算法
void shellSort(int a[], int n)  //a -- 待排序的数组, n -- 数组的长度
{
	int i, j, gap;   // gap为步长,每次减为原来的一半。
	for (gap = n / 2; gap > 0; gap /= 2)
	{
		// 共gap个组,对每一组都执行直接插入排序
		for (i = 0; i < gap; i++)
		{
			for (j = i + gap; j < n; j += gap)
			{
				// 如果a[j] < a[j-gap],则寻找a[j]位置,并将后面数据的位置都后移。
				if (a[j] < a[j - gap])
				{
					int tmp = a[j];
					int k = j - gap;
					while (k >= 0 && a[k] > tmp)
					{
						a[k + gap] = a[k];
						k -= gap;
					}
					a[k + gap] = tmp;
				}
			}
		}
	}
}
//打印数组的函数
void print(int a[], int n)
{
	for (int j = 0; j<n; j++)
	{
		cout << a[j] << "  ";
	}
	cout << endl;
}

//主函数
int main()
{
	int a[11] = { 70, 30, 40, 10, 80, 20, 90, 100, 75, 60, 45 };
	cout << "初始序列:";
	print(a, 11);
	shellSort(a, 11);
	cout << "排序结果:";
	print(a, 11);
	system("pause");
}

3.总结:

1.增量排序的时间复杂度依赖于所取增量序列的函数,但是到目前为止还没有一个最好的增量序列.有人在大量的实验后得出结论;当n在某个特定的范围后希尔排序的比较和移动次数减少至n^1.3 不管增量序列如何取值,都应该满足最后一个增量值为1。

2.有文献指出,当增量序列为d[k]=2(t-k+1)时,希尔排序的时间复杂度为O(n1.5), 其中t为排序趟数。

3.空间复杂度上,二分插入也是就地排序,空间复杂度为(O(1))。

猜你喜欢

转载自blog.csdn.net/qq_43801020/article/details/108108612