Shell 排序法 - 改良的插入排序

2023-11-09

说明

 

 插入排序法由未排序的后半部前端取出一个值,插入已排序前半部的适当位置,概念简单但速度不快。

排序要加快的基本原则之一,是让后一次的排序进行时,尽量利用前一次排序后的结果,以加快排序的速度,Shell排序法即是基于此一概念来改良插入排序法。

解法

 Shell排序法最初是D.L Shell于1959所提出,假设要排序的元素有n个,则每次进行插入排序时并不是所有的元素同时进行时,而是取一段间隔。

Shell首先将间隔设定为n/2,然后跳跃进行插入排序,再来将间隔n/4,跳跃进行排序动作,再来间隔设定为n/8、n/16,直到间隔为1之后的最 后一次排序终止,由于上一次的排序动作都会将固定间隔内的元素排序好,所以当间隔越来越小时,某些元素位于正确位置的机率越高,因此最后几次的排序动作将 可以大幅减低。

举个例子来说,假设有一未排序的数字如右:89 12 65 97 61 81 27 2 61 98

数字的总数共有10个,所以第一次我们将间隔设定为10 / 2 = 5,此时我们对间隔为5的数字进行排序,如下所示:

画线连结的部份表示 要一起进行排序的部份,再来将间隔设定为5 / 2的商,也就是2,则第二次的插入排序对象如下所示:

再来间隔设定为2 / 2 = 1,此时就是单纯的插入排序了,由于大部份的元素都已大致排序过了,所以最后一次的插入排序几乎没作什么排序动作了:

将间隔设定为n / 2是D.L Shell最初所提出,在教科书中使用这个间隔比较好说明,然而Shell排序法的关键在于间隔的选定,例如Sedgewick证明选用以下的间隔可以加 快Shell排序法的速度:

其中4*(2j)2 + 3*(2j) + 1不可超过元素总数n值,使用上式找出j后代入4*(2j)2 + 3*(2j) + 1求得第一个间隔,然后将2j除以2代入求得第二个间隔,再来依此类推。

后来还有人证明有其它的间隔选定法可以将Shell排序法的速度再加快;另外Shell排序法的概念也可以用来改良气泡排序法。

代码部分

#include <stdio.h> 
#include <stdlib.h> 
#include <time.h> 
#define MAX 10 
#define SWAP(x,y) {int t; t = x; x = y; y = t;} 

void shellsort(int[]); 

int main(void) { 
    int number[MAX] = {0}; 
    int i;  

    srand(time(NULL)); 

    printf("排序前:"); 
    for(i = 0; i < MAX; i++) { 
        number[i] = rand() % 100; 
        printf("%d ", number[i]); 
    } 

    shellsort(number); 

    return 0; 
} 

void shellsort(int number[]) { 
    int i, j, k, gap, t; 

    gap = MAX / 2; 

    while(gap > 0) { 
        for(k = 0; k < gap; k++) { 
            for(i = k+gap; i < MAX; i+=gap) { 
                for(j = i - gap; j >= k; j-=gap) { 
                    if(number[j] > number[j+gap]) { 
                        SWAP(number[j], number[j+gap]); 
                    } 
                    else 
                        break; 
                } 
            } 
        } 

        printf("\ngap = %d:", gap); 
        for(i = 0; i < MAX; i++) 
            printf("%d ", number[i]); 
        printf("\n"); 

        gap /= 2; 
    } 
} 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Shell 排序法 - 改良的插入排序 的相关文章

随机推荐

  • (2003, "Can't connect to MySQL server on 'IP' ([WinError 10061] 由于目标计算机积极拒绝,无法连接。)")

    2003 Can t connect to MySQL server on IP WinError 10061 与MySql 只能访问localhost 和 127 0 0 1访问 不能通过其他IP访问 问题描述 项目中跨域请求数据 在远程
  • 华为od机试 Python【游戏最高分】

    题目 小明正在和他的朋友们玩一个跳格子的游戏 这个游戏有一个行列 共包含n个格子 每个格子里都有一定的分数 游戏的规则如下 小明可以选择任意一个格子作为起点 从起点开始 小明可以选择跳到任意非相邻的格子 也就是说 如果小明当前在第i个格子
  • java中的resultset类详解

    一 JDBC sun 提供了一套通用性的接口 可以连接任何的数据库 连接数据库的具体得到实例 具体的数据库厂商实现的 连接数据的步骤 别忘了复制jar包 1 注册驱动 Class forName DriverManager 2 获得链接对象
  • CMD中提升帐户到管理员权限

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 提升用户权限 从打开的 命令提示符 窗口中 输入命令 net localgroup administrators 用户名 add 并按回车 即可给当前 用户名 提升为 管理
  • C++函数返回引用

    首先需要明白 C 函数为什么要返回引用 答 这样就不用返回结果的副本 因为返回副本需要做赋值拷贝函数 浪费时间 这时候 实际上 返回是结果的副本 而不是结果本身 如果要返回本身 就返回引用就OK了 例1 const string manip
  • 数据分析入门宝藏!《Python数据分析-从入门到实践》

    在大数据 人工智能时代 数据无处不在 无论处于哪种行业 能够掌握一定的数据分析技能必然是职场的加分项 本笔记提供了丰富的学习内容 包含230个快速示例 17个案例 4个项目 力求为读者打造一本 学习入门 应用 实践一体化 的的Python数
  • Presto 常用配置及操作

    一 介绍 Presto是一个开源的分布式SQL查询引擎 适用于交互式分析查询 数据量支持GB到PB字节 Presto的设计和编写完全是为了解决像Facebook这样规模的商业数据仓库的交互式分析和处理速度的问题 推荐阅读 Presto实现原
  • DVWA 通关XSS(Stored)

    存储型XSS 持久化跨站脚本 持久性体现在XSS代码不是在某个参数 变量 中 而是写进数据库文件等可以永久保存数据的介质中 存储型XSS通常发生在留言板等地方 可以在留言板位置进行留言 将恶意代码写进数据库中 Low 没有任何过滤 直接使用
  • 开源云同步的markdown写作软件——Yosoro

    文章目录 前言 简便的项目管理 舒服的写作体验 支持one driver 存在缺点 前言 Yosoro是一款支持在Win Linux macOS上使用的写作软件 它的界面设计以及交互上表达出的极简主义可以让用户们可以完全沉浸于自己写作世界
  • MyBatis学习——第四篇(拦截器和拦截器分页实现)

    MyBatis架构体图 1 mybatis核心对象 从MyBatis代码实现的角度来看 MyBatis的主要的核心部件有以下几个 SqlSession 作为MyBatis工作的主要顶层API 表示和数据库交互的会话 完成必要数据库增删改查功
  • 【git体验】git基础-3目录之间关系

    1 git目录和工作目录 Git目录并不是Bare repo 而是本地的代码库 即用git init命令在根目录创建的 git 目录 类似SVN的 svn 目录 这个目录就是git实现分布式代码管理的关鍵了 工作目录就是 git的上級目录
  • Angular&TypeScript 经验技巧

    TypeScript 变量声明 var 变量名 类型 值 基本类型 数据类型 关键字 描述 任意类型 any 声明为 any 的变量可以赋予任意类型的值 数字类型 number 双精度 64 位浮点值 它可以用来表示整数和分数 let bi
  • 使用HAL库开发STM32:使用Timer输出PWM信号

    文章目录 目的 基础说明 输出PWM信号 总结 目的 单片机输出PWM信号是很常用的一种功能需求 STM32中通常使用Timer来输出PWM信号 这篇文章将对相关内容做个说明 基础说明 在使用Timer输出PWM信号需要了解一些Timer的
  • Spring Boot, 访问入口配置

    HTTP Server port server port 8080 Make the application accessible on the given context path http localhost 8080 myapp se
  • openGL结合光照与纹理

    openGL系列文章目录 文章目录 openGL系列文章目录 前言 一 实现思路 二 代码 1 c 主程序 2 顶点着色器 3 片元着色器 运行效果 参考 源码下载 前言 在光照模型中 都是假设我们使用按ADS 定义的光源 照亮按ADS 定
  • Python计算商品复购率

    1 Python计算产品复购率 需求 给出数据商品购买数据 数据格式 csv 包含 购买月份 手机号 根据该数据计算产品的复购率 复购率算法 算法一 单位时间内 按每月 R 复购人数 总购买人数 算法二 单位时间内 按每月 R 复购交易次数
  • 应用usb_cam同时打开多个摄像头方法

    最近由于项目需要 需要同时开启多个摄像头 虽然可以用opencv去写对应的摄像头开启的程序 但是 还是想用ros中提供的usb cam去打开多个摄像头 通过usb cam去打开一个摄像头 不用下载源码 可以直接安装usb cam去调用lau
  • 使用GDI/GDI+绘制到D3D9缓冲区的方法

    这个其实是3D绘图里嵌入2D绘图的传统方式 D3D9直接使用GDI GDI 就可以画图 只不过需要额外的设置 而且只支持RGB和XRGB 不支持ARGB 因此这种方法比较适合合成UI元素和不透明的纹理贴图 不适合将要进行AlphaBlend
  • #Mybatis 关于mybatis的一级缓存

    本篇文章主要是为了帮助自己总结和加深理解 若能帮助到其他小伙伴也是极好的 基本介绍 Mybatis中支持一级缓存和二级缓存 一级缓存是默认开启的并且不能关闭 二级缓存默认关闭 可根据需要进行手动开启 总体来说Mybatis的一二级缓存的最终
  • Shell 排序法 - 改良的插入排序

    说明 插入排序法由未排序的后半部前端取出一个值 插入已排序前半部的适当位置 概念简单但速度不快 排序要加快的基本原则之一 是让后一次的排序进行时 尽量利用前一次排序后的结果 以加快排序的速度 Shell排序法即是基于此一概念来改良插入排序法