原理:基于快速排序的改进,减小待排数据规模
1、将原始待排数据进行分组,分成若干子序列
分组不是前10个一组,11~20一组;二是【1,11,21,...】一组,【2,12,22,...】一组
2、对这些子序列分别进行直接插入排序,使得整个数据基本有序
基本有序:小的基本在前面、大的基本在后面、不大不小的基本在中间
3、再对全体数据进行一次直接插入排序
注意:
- 增量序列的最后一个增量值必须为1
- 交换到末尾时,还要比较A[0]与A[增量]的大小
- 推荐阅读《大话数据结构》P391-396页
#include "pch.h"
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
long long cnt;
int l;
int A[1000000];
int n;
vector<int> G;
//指定了间隔g的直接插入排序
void insertionSort(int A[], int n, int g) {
for (int i = g; i < n; i++) {
int j = i - g;//
int v = A[i];//
while (j >= 0 && A[j] > v) {
//后一个更小
A[j + g] = A[j];
j -= g;//循环构造坐标等差数列进行排序
cnt++;
}
A[j + g] = v;
}
}
void shellsort(int A[], int n) {
//生成数列G={1,4,13,40,121,364,1093,...}
//由给定的n确定G的取值大小
for (int h = 1;;) {
if (h > n) {
break;
}
G.push_back(h);
h = h * 3 + 1;
}
for (int i = G.size() - 1; i >= 0; i--) {
//按逆序指定G[i]=g
insertionSort(A, n, G[i]);
}
}
int main()
{
cin >> n;
for (int i = 0; i < n; i++) {
scanf_s("%d", &A[i]);
}
cnt = 0;
shellsort(A, n);
cout << G.size() << endl;
for (int i = G.size() - 1; i >= 0; i--) {
printf("%d", G[i]);
if (i) printf(" ");
}
printf("\n");
printf("%d\n", cnt);
for (int i = 0; i < n; i++) {
printf("%d\n", A[i]);
}
return 0;
}