/* 希爾排序(Shell Sort)也稱為遞減增量排序,是插入排序的一種高速而穩定的改良版。
* 希爾排序是基於插入排序的以下兩點性質而提出改進方法的:
* # 插入排序在對幾乎已經排好序的資料操作時,效率高,即可以達到線性排序的效率
* # 但插入排序一般來說是低效的,因為插入排序每次只能將資料移動一位
* 對有n個元素可比較的資料,先取一個小於n的整數d₁作為第一個增量,把檔案的全部記錄分成d₁個組。
* 所有距離為d₁的倍數的記錄放在同一個組中。先在各組內進行直接插入排序;然後,取第二個增量d₂<d₁
* 重複上述的分組和排序,直至所取的增量為1,即所有記錄放在同一組中進行直接插入排序為止。
* 該方法實質上是一種分組插入方法。
* 已知的最好序列是{1,4,10,23,57,132,301,701,1750,...}。具有此分組序列的希爾排序比插入排序和堆排序
* 要快,但是,如果對小數組(少於50個元素)情況下比快速排序快,那麼對大數組就要比快速排序慢。在1750之後
* 的序列值按如下公式計算:next_step = round(step * 2.3)
* 在實際應用中,對於經典的shell分組序列{n/2,n/4,...,1},一般採用2.2作為遞減因子而不是2,這樣可以獲得
* 更好的效率。
*/
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <iterator>
#include <vector>
#include <algorithm>
using namespace std;
//const int N = 1000000;
const int N = 10;
typedef int ElementType;
typedef vector<int> VI;
typedef VI::const_iterator const_pVI;
void ShellSort(ElementType a[], int n);
void Print(ElementType a[], int n);
template<typename RandomIter, typename Compare>
void shell_sort(RandomIter begin, RandomIter end, Compare cmp);
template<typename RandomIter>
void shell_sort(RandomIter begin, RandomIter end);
ostream& operator<<(ostream& out, const VI& vi);
int main()
{
int a[N];
srand(time(NULL));
for (int i = 0; i < N; ++i)
a[i] = rand() % N;
VI vi(a, a + N);
cout << "排序前/n";
Print(a, N);
clock_t begin, end;
begin = clock();
ShellSort(a, N);
//sort(a, a + N);
end = clock();
double time_used = (double)(end - begin) / CLOCKS_PER_SEC;
cout << setprecision(3) << fixed << "耗時 " << time_used << "s" << endl;
cout << "排序後/n";
Print(a, N);
shell_sort(vi.begin(), vi.end());
cout << "排序後/n" << vi << endl;
return 0;
}
void ShellSort(ElementType a[], int n)
{
int i, j, increment;
ElementType temp;
for (increment = n / 2; increment > 0; increment /= 2)
for (i = increment; i < n; ++i) {
temp = a[i];
/*
for (j = i; j >= increment; j -= increment)
if (temp < a[j - increment])
a[j] = a[j - increment];
else
break;
*/
for (j = i; j >= increment && temp < a[j - increment]; j -= increment)
a[j] = a[j - increment];
a[j] = temp;
}
}
void Print(ElementType a[], int n)
{
for (int i = 0; i < n; ++i)
cout << a[i] << " ";
cout << endl;
}
template<typename RandomIter, typename Compare>
void shell_sort(RandomIter begin, RandomIter end, Compare cmp)
{
typedef typename iterator_traits<RandomIter>::value_type value_type;
typedef typename iterator_traits<RandomIter>::difference_type diff_t;
diff_t size = distance(begin, end);
diff_t step = size / 2;
while (step >= 1) {
for (diff_t i = step; i < size; ++i) {
value_type key = *(begin + i);
diff_t j = i;
while (j >= step && cmp(key, *(begin + j - step))) {
*(begin + j) = *(begin + j - step);
j -= step;
}
*(begin + j) = key;
}
if (step == 2)
step = 1;
else
step = static_cast<diff_t>(step / 2.2);
}
}
template<typename RandomIter>
void shell_sort(RandomIter begin, RandomIter end)
{
typedef typename iterator_traits<RandomIter>::value_type value_type;
shell_sort(begin, end, less<value_type>());
}
ostream& operator<<(ostream& out, const VI& vi)
{
for (const_pVI it = vi.begin(); it != vi.end(); ++it)
out << *it << " ";
out << endl;
return out;
}