2014.06.17 02:43

简介:

  希尔排序是插入排序的改进版。交换排序的目的,是通过交换,将逆序数降低为0。每交换一对相邻元素,逆序数变化为1。如果交换的元素不相邻,则逆序数的变化可能就大于1。希尔排序的思路,就是通过交换离得更远的两个元素,让逆序数更快地变为0(当然,并不总是管用)。

描述:

  我们定义一个间隔k,每隔k各元素选取一次,可以选出一个子数组。那么可以找出k个这样的子数组。对于每个子数组进行插入排序,这样的插入排序中,每交换一次减少的逆序数可能大于1,从而提高效率。但排序以后k个子数组之间没有进行比较,因此我们再选取另一个间隔k’,再来一轮。实际上,这样的间隔序列可以自己定义,只要合理即可。通过查资料可以找到前辈们总结的比较靠谱的间隔序列。一种简单直观的间隔序列,就是{n / 2, n / 4, n / 8, ..., 1}。这是明显的折半,但注意不要把顺序反过来。理由很明显:如果你一开始就选1作为间隔,那就是插入排序,剩余的间隔排序就没有意义了,效率自然也不会提高。关于希尔排序的复杂度,不一定是O(n^2),要根据选取的间隔序列来分析。

实现:

 1 // My implementation for shell sort.
 2 #include <iostream>
 3 #include <vector>
 4 using namespace std;
 5 
 6 void shellSort(vector<int> &v)
 7 {
 8     int n, i, j;
 9     int tmp;
10     int increment;
11     
12     n = (int)v.size();
13     for (increment = n / 2; increment > 0; increment /= 2) {
14         for (i = increment; i < n; ++i) {
15             tmp = v[i];
16             for (j = i; j >= increment && v[j - increment] > tmp; j -= increment) {
17                 v[j] = v[j - increment];
18             }
19             v[j] = tmp;
20         }
21     }
22 }
23 
24 int main()
25 {
26     vector<int> v;
27     int n, i;
28     
29     while (cin >> n && n > 0) {
30         v.resize(n);
31         for (i = 0; i < n; ++i) {
32             cin >> v[i];
33         }
34         shellSort(v);
35         for (i = 0; i < n; ++i) {
36             cout << v[i] << ' ';
37         }
38         cout << endl;
39     }
40     
41     return 0;
42 }

 

 posted on 2014-06-17 02:57  zhuli19901106  阅读(395)  评论(0编辑  收藏  举报