[排序算法] 希尔排序 (C++)
前言
本文章是建立在插入排序的基础上写的喔,如果有对插入排序还有不懂的童鞋,可以看看这里。
直接/折半插入排序 2路插入排序
希尔排序解释
希尔排序 Shell Sort 又名"缩小增量排序",是对直接插入排序更加高效的改进版本。它是由 Donald Shell 于1959年提出的一种排序算法。
希尔排序 其原理是设置一个增量incre,在原序列上每隔一个增量选取一个数据元素,将这些选取的元素构造成一个子序列。
每设一个增量,我们每次会得到一组子序列 (子序列个数和当前增量相等),然后分别对这些子序列进行 直接插入排序 。
随着增量的减少,重复上述的操作,直到增量incre为 1 时,最后完成整个序列的排序。
希尔排序增量的选取
原始希尔增量
对于 希尔排序 的增量的选取,Donald Shell 一开始提出增量每次为上次的 1/2。
也就是说,若数组长度为n,一开始增量为 n/2,之后每次增量都取上次的 1/2。
Knuth序列
Knuth序列:以逆向形式从1开始,通过递归表达式 interval = 3 * interval + 1 来产生,以此来得到间隔大小。
由此我们可以得到如下的增量选取方式:
具体方法是若数组长度为n,一开始增量取 n/3 向下取整 + 1。然后每次都取上次的增量的 1/3向下取整 + 1。
当n足够大时,使用 Knuth序列 得到的增量选取方式,可以一定程度上提高希尔排序的效率。
(上面说的东西其实我也不知道对不对,至于为什么这样取,我也不知道哇哇哇 )
(在后文的程序中,我会采取此方式选取增量。)
希尔排序动态演示
我们以 [6,5,2,4,1,3] 为例进行动态演示
第一次取增量,构造一组子序列

第一次取增量后,对每个子序列进行直接插入排序

第二次取增量,构造一组子序列

第二次取增量后,对每个子序列进行直接插入排序

第三次取增量,构造一组子序列

第三次取增量后,对每个子序列进行直接插入排序

希尔排序时间复杂度
对于 希尔排序 的时间复杂度,我真的研究了好久,用尽自己毕生所学的高数知识。
但是能力有限,最终没有探索出什么结果呜呜呜(是我太菜了对不起)
不过有人通过大量的实验,给出了较好的结果:当n较大时,比较和移动的次数约在 n^1.25 到 (1.6n)^1.25 之间。
希尔排序核心代码
//设置增量 每隔一个增量取一个数 组成长度相同的子序列
void ShellSort(vector<int> &v){
int n = v.size();
int incre = n; //初始化增量
while(incre > 1){ //最后一次增量为1
incre = incre / 3 + 1; //除三向下取整加一
//(至于为什么这样取, 哇咖喱嘛三)
for(int i = incre; i < n; i++){
int key = v[i]; //当前需要插入的数
int j = i - incre;
while(j >= 0 && v[j] > key){
v[j + incre] = v[j];
j -= incre; //对每个子序列进行直接插入排序
}
v[j + incre] = key; //插入到合适位置
}
}
}
完整程序源代码
#include<iostream>
#include<vector>
#include<time.h>
using namespace std;
//设置增量 每隔一个增量取一个数 组成长度相同的子序列
void ShellSort(vector<int> &v){
int n = v.size();
int incre = n; //初始化增量
while(incre > 1){ //最后一次增量为1
incre = incre / 3 + 1; //除三向下取整加一
//(至于为什么这样取, 哇咖喱嘛三)
for(int i = incre; i < n; i++){
int key = v[i]; //当前需要插入的数
int j = i - incre;
while(j >= 0 && v[j] > key){
v[j + incre] = v[j];
j -= incre; //对每个子序列进行直接插入排序
}
v[j + incre] = key; //插入到合适位置
}
}
}
void show(vector<int> &v){
for(auto &x : v)
cout<<x<<" ";
cout<<endl;
}
main(){
vector<int> v;
int n = 50;
srand((int)time(0));
while(n--)
v.push_back(rand() % 100 + 1);
show(v);
ShellSort(v);
cout<<endl<<endl;
show(v);
}
程序运行结果图

[排序算法] 希尔排序 (C++)的更多相关文章
- 排序算法--希尔排序(Shell Sort)_C#程序实现
排序算法--希尔排序(Shell Sort)_C#程序实现 排序(Sort)是计算机程序设计中的一种重要操作,也是日常生活中经常遇到的问题.例如,字典中的单词是以字母的顺序排列,否则,使用起来非常困难 ...
- 数据结构和算法(Golang实现)(22)排序算法-希尔排序
希尔排序 1959 年一个叫Donald L. Shell (March 1, 1924 – November 2, 2015)的美国人在Communications of the ACM 国际计算机 ...
- 使用 js 实现十大排序算法: 希尔排序
使用 js 实现十大排序算法: 希尔排序 希尔排序 refs xgqfrms 2012-2020 www.cnblogs.com 发布文章使用:只允许注册用户才可以访问!
- C数据结构排序算法——希尔排序法用法总结(转http://www.cnblogs.com/skywang12345/p/3597597.html)
希尔排序介绍 希尔排序(Shell Sort)是插入排序的一种,它是针对直接插入排序算法的改进.该方法又称缩小增量排序,因DL.Shell于1959年提出而得名. 希尔排序实质上是一种分组插入方法.它 ...
- Python排序算法——希尔排序(Shell’s Sort)
有趣的事,Python永远不会缺席! 如需转发,请注明出处:小婷儿的python https://www.cnblogs.com/xxtalhr/p/10793487.html 一.希尔排序(Shel ...
- js 实现排序算法 -- 希尔排序(Shell Sort)
原文: 十大经典排序算法(动图演示) 希尔排序 1959年Shell发明,第一个突破O(n2)的排序算法,是简单插入排序的改进版.它与插入排序的不同之处在于,它会优先比较距离较远的元素.希尔排序又叫缩 ...
- JavaScript排序算法——希尔排序
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 排序算法-希尔排序(Java)
package com.rao.sort; import java.util.Arrays; /** * @author Srao * @className ShellSort * @date 201 ...
- Java排序算法——希尔排序
package sort; //================================================= // File Name : ShellSort //------- ...
- 数据结构和算法(Golang实现)(20)排序算法-选择排序
选择排序 选择排序,一般我们指的是简单选择排序,也可以叫直接选择排序,它不像冒泡排序一样相邻地交换元素,而是通过选择最小的元素,每轮迭代只需交换一次.虽然交换次数比冒泡少很多,但效率和冒泡排序一样的糟 ...
随机推荐
- [GWCTF 2019]我有一个数据库 WP
打开环境访问看到 提示我有一个数据库,但里面什么都没有,于是拿dirsearch跑了一下,没有出结果 但是有数据库嘛,那么试试常见的几个加上phpmyadmin 试试 于是看到了版本是4.8.1 拿到 ...
- centos使用Yum安装postgresql 13
rpm源安装 yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat ...
- kubernetes1.20 部署 traefik2.3
一.概述 Traefik 是一个开源的可以使服务发布变得轻松有趣的边缘路由器.它负责接收你系统的请求,然后使用合适的组件来对这些请求进行处理. 除了众多的功能之外,Traefik 的与众不同之处还在于 ...
- win10系统应用商店打开后无法联网 代码: 0x80131500 的解决办法
官方提供的建议网址: https://answers.microsoft.com/zh-hans/windows/forum/all/代码/cbbe7aaf-8f66-4779-89c8-3c74f5 ...
- vue-router query和params 传参和接收参数
1.params 方式传递和接收参数 //传参 this.$router.push({ name: 'checkDetailInfo', params:{ fkdNum:fkdNum, jyayStr ...
- aardio + AutoHotkey 混合编程
本文主要介绍 aardio + AutoHotkey 混合编程. 在 aardio 中可以调用很多编程语言,例如 C语言.C++.C#.Java.Python.R.Javascript.Node.Js ...
- Go实现优雅关机与平滑重启
前言 优雅关机就是服务端关机命令发出后不是立即关机,而是等待当前还在处理的请求全部处理完毕后再退出程序,是一种对客户端友好的关机方式.而执行Ctrl+C关闭服务端时,会强制结束进程导致正在访问的请求出 ...
- 关于aws cli命令的exit/return code分析
最近总是收到一个备份脚本的失败邮件,脚本是之前同事写的,没有加入任何有调试信息,及有用的日志 于是去分析 ,脚本中有一条 aws s3 sync $srclocal $dsts3 命令,然后根据这条 ...
- EFCore (二)之 跟踪实体
核心 SaveChanges() "已分离"和"未改变"的实体,SaveChanges()忽略: "已添加"的实体,SaveChanges( ...
- KubeEdge 1.12版本发布,稳定性、安全性、可扩展性均带来大幅提升
摘要:2022年9月29日,KubeEdge发布1.12版本.新版本新增多个增强功能,在扩展性.稳定性.安全性上均有大幅提升. 本文分享自华为云社区<KubeEdge 1.12版本发布,稳定性. ...