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 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)