希尔排序 Shell Sort

原理:基于快速排序的改进,减小待排数据规模

1、将原始待排数据进行分组,分成若干子序列

     分组不是前10个一组,11~20一组;二是【1,11,21,...】一组,【2,12,22,...】一组

2、对这些子序列分别进行直接插入排序,使得整个数据基本有序

     基本有序:小的基本在前面、大的基本在后面、不大不小的基本在中间

3、再对全体数据进行一次直接插入排序

注意:

  1. 增量序列的最后一个增量值必须为1
  2. 交换到末尾时,还要比较A[0]与A[增量]的大小
  3. 推荐阅读《大话数据结构》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;
}

猜你喜欢

转载自blog.csdn.net/qq_39883358/article/details/83069971