希尔排序 - 数据结构 - 算法


超全经典排序大汇总


算法思想

先将序列分为若干个子序列,然后对各个子序列进行直接插入排序,等到序列基本有序时,再对整个序列进行一次直接插入排序。即先追求表中的元素部分有序,再逐渐逼近全局有序。

优点:

让关键字值小的元素能能够很快移动到前面,且序列基本有序时进行直接插入排序时间效率会提升很多。

时间复杂度

  1. 最好 — 无 无
  2. 最坏 — O ( n 2 ) O(n^2) O(n2)
  3. 平均 — O ( n 1.3 ) O(n^{1.3}) O(n1.3)

演示动画

希尔.gif

空间复杂度 O(1)

使用数组头号元素a[0]

稳定性

不稳定

适用性

仅适用于顺序表

算法特点

  1. 记录跳跃式地移动导致排序方法是不稳定的
  2. 只能用于顺序结构,不能用于链式结构
  3. 增量序列可以有各种取法,但应该使增量序列中的值没有除以以外的公因子,并且最后一个增量值必须为1
  4. 记录总的比较次数和移动次数都比直接插入排序要少,n月大时,效果越明显。适合初始记录无序,n较大时的情况。

核心代码

//希尔排序 
void ShellSort(int a[], int n){
	int d, i, j;
	for(d = n / 2; d >= 1; d /= 2){//d为增量,增量序列依次折半(算法原创作者本人推荐) 
		for(i = d + 1; i <= n; i ++){//处理局部序列 
			if(a[i] < a[i - d]){
				a[0] = a[i];//暂存当前待处理元素 
				for(j = i - d; j > 0 && a[0] < a[j]; j -= d){
					a[j + d] = a[j];//局部元素后移 
				}
				a[j + d] = a[0];//在合适位置处插入当前元素 
			}
		}
	}
}

完整代码

#include <iostream> 
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <fstream>

using namespace std;
const int N = 20;

int num;
int data[N],idx;

//希尔排序 
void ShellSort(int a[], int n){
	int d, i, j;
	for(d = n / 2; d >= 1; d /= 2){//d为增量,增量序列依次折半(算法原创作者本人推荐) 
		for(i = d + 1; i <= n; i ++){//处理局部序列 
			if(a[i] < a[i - d]){
				a[0] = a[i];//暂存当前待处理元素 
				for(j = i - d; j > 0 && a[0] < a[j]; j -= d){
					a[j + d] = a[j];//局部元素后移 
				}
				a[j + d] = a[0];//在合适位置处插入当前元素 
			}
		}
	}
}

int main(){
	//打开文件 
	ifstream infile;
	infile.open("D:\\学习\\数据结构\\第8章排序\\in.txt", ios::in);
	
	//写文件 
	ofstream outfile;
	outfile.open("D:\\学习\\数据结构\\第8章排序\\out.txt", ios::out);
	
	if(!infile.is_open()){//判断文件打开是否成功 
		cout << "file open failure!" << endl;
	}
	
	infile >> num;//读取元素个数 
	while(num --){//将文件中的元素复制到data[1...n] 数组中
		infile >> data[++ idx];
	}
	
	cout << "排序前元素序列:" << endl;
	for(int i = 1; i <= idx; i ++) cout << data[i] << ' '; cout << endl;
	
	cout << "使用sort函数排序后序列: " << endl;
	sort(data + 1, data + 1 + idx); 
	for(int i = 1; i <= idx;  i++) cout << data[i] << ' '; cout << endl;
	
	ShellSort(data, idx);
	cout << "使用希尔排序后序列为:" << endl;
	for(int i = 1; i <= idx;  i++) cout << data[i] << ' '; cout << endl;
	
	num = idx, idx = 0, outfile << num << endl;//写入数据数num以及在行末写入\n 
	while(num --){
		outfile << data[++ idx] << ' ';//将排序后的数据写到文件中 
	}
	outfile << endl;//向文件末尾写入\n结束符 
	
	
	//关闭文件 
	infile.close();
	outfile.close();
	return 0;
}

输入数据(in.txt)

10
13 69 86 99 59 23 64 32 86 72

输出数据(out.txt)

10
13 23 32 59 64 69 72 86 86 99 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

soyisou

您的鼓励将是我创作的最大动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值