希尔排序

希尔排序

基本思想:希尔排序是把序列按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量的逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个序列恰好被分为一组,算法便终止。

算法实现:希尔排序需要定义一个增量,这里选择增量为gap=length/2,缩小增量以gap=gap/2的方式,这个增量可以用一个序列来表示,{n/2,(n/2)/2…1},称为增量序列,这个增量是比较常用的,也是希尔建议的增量,称为希尔增量,但其实这个增量序列不是最优的。

(1)对于一个无序序列{8,9,1,7,2,3,5,4,6,0}来说,我们初始增量为gap=length/2=5,所以这个序列要被分为5组,分别是{8,3},{9,5},{1,4},{7,6},{2,0},对这5组分别进行直接插入排序,则小的元素就被调换到了前面,然后再缩小增量gap=gap/2=2。
在这里插入图片描述
(2)上面缩小完增量后,序列再次被分为2组,分别是{3,1,0,9,7}和{5,6,8,4,2},再对这两组进行直接插入排序,那么序列就更加有序了。
在这里插入图片描述
(3)然后再缩小增量gap=gap/2=1,这时整个序列就被分为一组即{0,2,1,4,3,5,7,6,9,8},最后再进行调整,就得到了有序序列{0,1,2,3,4,5,6,7,8,9}。
在这里插入图片描述

代码实现:

#include <iostream>
#include <vector>

using namespace std;

vector<int> ShellSort(vector<int> list){
	vector<int> result = list;
	int n = result.size();
	for (int gap = n >> 1; gap > 0; gap >>= 1){
		for (int i = gap; i < n; i++){
			int temp = result[i];
			int j = i - gap;
			while (j >= 0 && result[j] > temp){
				result[j + gap] = result[j];
				j -= gap;
			}
			result[j + gap] = temp;
		}
		for (int i = 0; i < result.size(); i++){
			cout << result[i] << " ";
		}
		cout << endl;
	}
	return result;
}

void main(){
	int arr[] = { 6, 4, 8, 9, 2, 3, 1 };
	vector<int> test(arr, arr + sizeof(arr) / sizeof(arr[0]));
	cout << "排序前" << endl;
	for (int i = 0; i < test.size(); i++){
		cout << test[i] << " ";
	}
	cout << endl;
	vector<int> result;
	result = ShellSort(test);
	cout << "排序后" << endl;
	for (int i = 0; i < result.size(); i++){
		cout << result[i] << " ";
	}
	cout << endl;
	system("pause");
}

三、算法分析
1、希尔排序的算法性能
排序:希尔排序
在这里插入图片描述

1、时间复杂度
步长的选择是希尔排序的重要部分,只要最终步长为1任何步长序列都可以工作。

算法最开始以一定的步长进行排序。然后会继续以一定步长进行排序,最终算法以步长为1进行排序。当步长为1时,算法变为插入排序,这就保证了数据一定会被排序。

步长序列的不同,会导致最坏的时间复杂度情况的不同。

本文中,以N/2为步长的最坏时间复杂度为N^2。
用这样步长序列的希尔排序比插入排序要快,甚至在小数组中比快速排序和堆排序还快,但是在涉及大量数据时希尔排序还是比快速排序慢。

2、算法稳定性
希尔排序中相等数据可能会交换位置,所以希尔排序是不稳定的算法。

3、直接插入排序和希尔排序的比较
直接插入排序是稳定的;而希尔排序是不稳定的

直接插入排序更适合于原始记录基本有序的集合。

希尔排序的比较次数和移动次数都要比直接插入排序少,当N越大时,效果越明显。

希尔排序的比较次数和移动次数都要比直接插入排序少,当N越大时,效果越明显。

直接插入排序也适用于链式存储结构;希尔排序不适用于链式结构

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值