希尔排序:前面介绍过插入排序,要提高算法效率,我们必须一次消去不止1个逆序对,比如交换相隔较远的2个元素,所以这里引入希尔排序,每次交换的两个元素相隔较远,所以一次交换消除不止一对逆序对,会加快排序过程。
- 定义增量序列DM>DM-1>...>D1=1
- 对每个Dk进行“Dk-间隔”排序(k=M,M-1,...,1)
- 注意:“Dk-间隔”有序的序列,在执行“Dk-1-间隔” 排序后,任然是“Dk-间隔”有序的
Hibbard 增量序列
- Dk = 2k-1 — 相邻元素互质
- 最坏情况:T=Θ(N^3/2)
- 猜想:Tavg=O(N^5/4)
Sedgewick增量序列
- {1, 5, 19, 41, 109, … } 9×4^i – 9×2^i + 1 或 4i – 3×2^i + 1
- 猜想: Tavg=O(N7/6),Tworst=O(N^4/3)
//O(n^d) O(1)
#include<bits/stdc++.h>
using namespace std;
void shellSort(vector<int>& arr) { //使用Sedgewick增量序列
int n = arr.size();
int si,D,P,i,tmp=0;
/* 这里只列出一小部分增量 */
int Sedgewick[] = { 929, 505, 209, 109, 41, 19, 5, 1, 0 };
for (si = 0; Sedgewick[si] >= n; si++) {} //初始的增量Sedgewick[Si]不能超过待排序列长度
for (D = Sedgewick[si]; D > 0; D = Sedgewick[++si]) { //每次更改间隔D的大小
for (P = D; P < n; P++) { //将原来插入排序数字1全部改为间隔D
tmp = arr[P];
for (i = P; i >= D && arr[i - D] > tmp; i -= D) {
arr[i] = arr[i - D];
}
arr[i] = tmp;
}
}
}
int main() {
vector<int> arr = { 8,6,10,7,9,4,3,2,5,1 };
shellSort(arr);
for (auto x : arr) {
cout << x << " ";
}
cout << endl;
system("pause");
return 0;
}
1 2 3 4 5 6 7 8 9 10
请按任意键继续. . .
性能分析:原始希尔排序的增量序列是N/2,会出现增量元素不互质,则小的增量可能根本不起作用,所以采用Hibbard增量序列或者Sedgewick增量序列。由于隔位进行交换,所以不是稳定的排序算法。
- 最坏情况:T=Θ(N^2)
- 稳定性:不稳定