超全经典排序大汇总
算法思想
先将序列分为若干个子序列,然后对各个子序列进行直接插入排序,等到序列基本有序时,再对整个序列进行一次直接插入排序。即先追求表中的元素部分有序,再逐渐逼近全局有序。
优点:
让关键字值小的元素能能够很快移动到前面,且序列基本有序时进行直接插入排序时间效率会提升很多。
时间复杂度
- 最好 — $O无$
- 最坏 — $O(n^2)$
- 平均 — $O(n^1.3)$
演示动画
空间复杂度 O(1)
使用数组头号元素a[0]
稳定性
不稳定
适用性
仅适用于顺序表
算法特点
- 记录跳跃式地移动导致排序方法是不稳定的
- 只能用于顺序结构,不能用于链式结构
- 增量序列可以有各种取法,但应该使增量序列中的值没有除以以外的公因子,并且最后一个增量值必须为1
- 记录总的比较次数和移动次数都比直接插入排序要少,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