数据结构与算法基础(王卓)(33):折半插入排序、希尔排序

news2025/1/16 3:30:00

目录

折半插入排序

 Project 1:

问题:缺少在插入元素之前的移动元素的操作

Project 2:(最终成品、结果)

希尔排序

 Project 1:(个人思路)

标准答案:(PPT答案)

解释说明:(在程序实际执行的时候的算法运行逻辑顺序实际上和王卓老师网课中所讲的有所不同)

(1):赋值阶段

(2):第一轮【第一次】比较

 (3):第二轮到第(d)轮【第一次】比较

(4):第一轮到第(d)轮【第2次及其后续的】比较

重点来了:

至于如何调整先后进行比较时,不同的间隔大小d的问题,这里标准答案给出的方法是:

王道答案:

本土化


折半插入排序


直接根据实际实例、根据草图写出如下程序: 

 Project 1:

void BinsertSort(SqList& L)
{
    int i ,low = 1, high = i - 1;
    for (i = 1; i < L.length; i++)
    {
        if (L.r[i].key < L.r[i - 1].key)
            L.r[0] = L.r[i];
        //if可以放到最高优先级
        for (int mid = (low + high) / 2; high > low; mid = (low + high) / 2)
        {
            if (L.r[0].key < L.r[mid].key)
                high = mid - 1;
            else //if (L.r[0].key > L.r[mid].key)
                low = mid + 1;
        }
        L.r[high + 1].key = L.r[0].key;
        //L.r[low - 1].key = L.r[0].key;
    }
}

binary insert;
binary:二进制的; 仅基于两个数字的; 二元的; 由两部分组成的;

问题:缺少在插入元素之前的移动元素的操作


Project 2:(最终成品、结果)

void BinsertSort(SqList& L)
//binary insert;
//binary:二进制的; 仅基于两个数字的; 二元的; 由两部分组成的;
{
    int i;
    for (i = 1; i < L.length; i++)
        //i表示位序
    {
        if (L.r[i].key < L.r[i - 1].key)
            L.r[0] = L.r[i];
int low = 1, high = i - 1;
        for (int mid = (low + high) / 2; high > low; mid = (low + high) / 2)
        {
            if (L.r[0].key < L.r[mid].key)
                high = mid - 1;
            else //if (L.r[0].key > L.r[mid].key)
                low = mid + 1;
        }
        for (int j = i; j >= high + 1; j--)
            L.r[j + 1].key = L.r[j].key;

        L.r[high + 1].key = L.r[0].key;
        //L.r[low - 1].key = L.r[0].key;
    }
}

希尔排序

直接根据实际实例、根据草图写出如下程序: 

 Project 1:(个人思路)

void ShellSort(SqList& L) 
{
    for (int i = 0; i <= L.length / 5; i++)
    {
        for (int i = 0; i <= L.length; i += 5)
        {
            每次都把数据存储到中序二叉树,再用中序遍历把这些元素全部都重新插回去
        }
        递归...
    }
}

标准答案:(PPT答案)

void ShellInsert(SqList& L, int d)
//distance:每次一步往后跨多远(5,3,1...)
{
    int i, j;
    for (i = d + 1; i < L.length; i++) 
    {
        if (L.r[i].key < L.r[i - d].key) 
            //比较的诸多元素里,第二个元素大于第一个元素
        {
            L.r[0] = L.r[i];  
            for (j = i - d; //第一个元素
                j > 0 && (L.r[0].key < L.r[j].key);
                j -= d)
                L.r[j + d] = L.r[j];  //记录后移
            L.r[j + d] = L.r[0];  
        }
    }
}
void ShellSort(SqList& L, int dlta[], int t)
//t:循环总共趟数
{
    for (int k = 0; k < t; k++)
        ShellInsert(L, dlta[k]); 
    //dlta[k]:增量(5, 3, 1...)
}

解释说明:(在程序实际执行的时候的算法运行逻辑顺序实际上和王卓老师网课中所讲的有所不同)


(1):赋值阶段

i 的初值为每次比较的第二个元素

比较的诸多元素里,若第二个元素大于第一个元素:开始循环


(2):第一轮【第一次】比较

第一轮比较的第一次操作,只比较前面选中的两个元素而已:


比较第1个和第(d+1)个元素

  1. 把第二个元素放进哨兵
  2. 第一个元素覆盖第二个元素
  3. 再把第二个元素从哨兵里转移到第一个元素的位置

然后:j-=d;    =>     j<0


第一轮比较结束

实际上完整的这个分块的排序没有结束

但是由于实际上希尔排序和老师讲的算法思路有所偏差

所以,对于:我们把数据分成d份,共进行d轮排序的第一轮算法,就在这里先暂停终止了


然后(在第一轮的比较结束后),我们进行的操作并不是像王老师所说:

去找下一个分块筛选出的,第三个以及后续的其他元素进行比较和排序

而是暂时中止这个分块算法操作,去找我们存储在数据内部的第二个元素:


 (3):第二轮到第(d)轮【第一次】比较

比较:

第2个和第(d+2)个,第3个和第(d+3)个,第4个和第(d+4)个......

直到比较到第(d)轮:第d个和第(d*2)个

现在,我们已经拥有了前2d个分门别类排序好的元素序列:

前d个元素(k:位序)

分别小于

后面的第(d+k)位元素


(4):第一轮到第(d)轮【第2次及其后续的】比较

类似(2)、(3)比较的步骤,继续往后比较,直到后续元素全部都被比较完为止:

 但是,这个地方(第四步)里面:

在每次比较完【通过我们定义的序列规则(每隔d个为一组)区分开来的】

里面的最后两个元素以后

我们还进行一个超越(2)、(3)步骤的操作:

对每一组的序列前面的所有元素全部都重新进行一遍遍历

也就是说:

每一组队列序列在比较完最后两个元素以后,继续向前逐个比较

如果/但凡  比较时后面的元素小于前面的元素,就把后面的元素放到前面去


重点来了:

总共比较的数据范围不止两个了以后,在每一轮每一次的比较时:每次都

继续拿【比较后较小的元素】不断和【再前面的一个序列里的元素】进行比较

由 i 新指向的元素开始,把整个该组序列前面的元素全部都比较个遍


在这个过程中,我们就完成了“排序”操作的整个/所有的流程(过程):

逐个比较

把小的元素调换到前面的位置(碰到小的往前面移)

大的元素调换到后面的位置(碰到大的往后面挪)

 而在比较的数据范围不止两个了以后,每次对元素进行比较时

都把前面所有的元素都比较个遍(遍历个遍)的操作,很简单,在程序每次比较的循环里加一句:

一直向前面一个元素进行比较,直到本序列前面所有元素都被比较完毕为止

这样就完成了 :

            for (j = i - d; //第一个元素
                j > 0 && (L.r[0].key < L.r[j].key);
                j -= d)

这一段程序执行的for语句设计代码

是这整一个算法程序的运行流程的框架构建核心和精妙之处所在 


至于如何调整先后进行比较时,不同的间隔大小d的问题,这里标准答案给出的方法是:

每次通过某一规则dlta[ ]

(函数?还是什么???他这里也没有给出每次的对应关系,我TM也不知道他在搞的是个什么东西)来进行某种有规律性的变化:

    for (int k = 0; k < t; k++)//t:循环总共趟数
        ShellInsert(L, dlta[k]); 

我这里都被他整得(搞得)有点迷糊了,我也不知道他在搞什么东西


既然觉得他写的这个控制方法是一坨大便,那么我们不妨来看看这个每次都将所有数据二分的操作实例:

王道答案:

//希尔排序
void ShellSort(int A[], int n)
{
    int d, i, j;
    //A[0]只是暂存单元,不是哨兵,当j<=0时,插入位置已到
    for (d = n / 2; d >= 1; d = d / 2)
        //步长变化
        for (i = d + 1; i <= n; ++i)
            if (A[i] < A[i - d])
                //需将A[i]插入有序增量子表
            {
                A[0] = A[i];
                //暂存在A[0]
                for (j = i - d; j > 0 && A[0] < A[j]; j -= d)
                    A[j + d] = A[j];
                //记录后移,查找插入的位置
                A[j + d] = A[0];
            }//if
}

根据我们设立的前置条件,按照要求进行修改:(将程序本土化)

本土化:

void ShellSort(SqList& L)
{
    int  i, j;
    for (int d = L.length / 2; d >= 1; d = d / 2)
        //步长变化

        for (i = d + 1; i <= L.length; ++i)
            if (L.r[i].key < L.r[i - d].key)
            {
                L.r[0] = L.r[i];
                for (j = i - d; j > 0 && L.r[0].key < L.r[j].key; j -= d)
                    L.r[j + d] = L.r[j];
                L.r[j + d] = L.r[0];
            }//if
}

这样看来,其实(实际上),程序用来控制每次不断比较的补偿d的程序,也只是需要一段:

    for (int d = L.length / 2; d >= 1; d = d / 2)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/491427.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

OpenGL(六)——坐标系统

目录 一、前言 二、空间系 2.1 局部空间 2.2 世界空间 2.3 观察空间 2.4裁剪空间 2.5 正射投影 2.6 透视投影 2.7 屏幕空间 三、透视箱子 3.1 创建模型矩阵 3.2 创建观察矩阵 3.3 创建透视投影矩阵 3.4 修改顶点着色器 3.5 传递变换矩阵 四、旋转的箱子 五、好…

面了一圈,还没拿到offer.....

最近收到很多小伙伴的留言&#xff0c;金三银四过完了一个offer都没收到。还有遇到那种特别喜欢怼人的面试官&#xff0c;直接面到怀疑人生&#xff0c;真是让人费解。。。 其实面试受打击是正常的&#xff0c;关键是要在面试中总结自己的不足&#xff01;提前做好面试准备和技…

java基于知识库的中医药问询系统

本系统主要包含了等系统用户管理、中医药常识管理、科室信息管理、知识库管理多个功能模块。下面分别简单阐述一下这几个功能模块需求。 管理员的登录模块&#xff1a;管理员登录系统对本系统其他管理模块进行管理。 用户的登录模块&#xff1a;用户登录本系统&#xff0c;对个…

简历投了2个月没有面试,看这趋势,不发力是不行了

最近有朋友吐槽&#xff0c;感觉最近好难&#xff0c;简历投了2个月了&#xff0c;面试机会很少&#xff0c;自己每天也费心费力的投&#xff0c;一有新职位就赶紧投&#xff0c;自己也积极的跟人家打招呼&#xff0c;不是看完那边没有回复&#xff0c;要么就是不合适。于是我就…

基于ARM树莓派实现智能家居:语音识别控制,Socket网络控制,火灾报警检测,实时监控

目录 一 项目说明 ① 设计框架 ② 功能说明 ③ 硬件说明 ④ 软件说明 二 项目代码 <1> mainPro.c 主函数 <2> InputCommand.h 控制设备头文件 <3> contrlDevices.h 外接设备头文件 <4> bathroomLight.c 泳池灯 <5> livin…

【GUI】基于Python的文本数据处理(串口解析 0D 0A结尾)

【GUI】基于Python的文本数据处理&#xff08;串口解析 0D 0A结尾&#xff09; 如有串口数据&#xff1a; [37;22mD/NO_TAG [2023-04-24 23:01:06 ] ------------------------------------------------->>>>>> M_DADAT_GET_DAMAGE_INFO [0m 2023/04/24 2…

200左右什么蓝牙耳机比较好?国产200左右蓝牙耳机推荐

随着不少手机厂商取消3.5mm耳机孔&#xff0c;蓝牙耳机便成为了人们外出的最佳选择。最近看到很多人问&#xff0c;200左右什么蓝牙耳机比较好&#xff1f;针对这个问题&#xff0c;我来给大家推荐几款国产的蓝牙耳机&#xff0c;一起来看看吧。 一、南卡小音舱Lite2蓝牙耳机 …

如何防止订单重复支付

想必大家对在线支付都不陌生&#xff0c;今天和大家聊聊如何防止订单重复支付。 看看订单支付流程 我们来看看&#xff0c;电商订单支付的简要流程&#xff1a; 订单钱包支付流程 从下单/计算开始&#xff1a; 下单/结算&#xff1a;这一步虽然不是直接的支付起点&#xff0c;但…

opencv场景识别

opencv场景识别 文章目录 一、需求1、现状2、设想 二、模型使用1、opencv dnn支持的功能2、ANN_MLP相关知识3、MLP图像分类模型训练学习 三、更换方向1、目标检测模型2、darknet网络介绍 四、opencv调用darknet模型1、**darknet模型获取**2、python调用darknet模型3、遇到的一些…

NewBing最新更新使用体验(无需等待人人可用)

NewBing最新更新使用体验 微软Bing爆炸级更新&#xff01;无需等待人人可用&#xff01; 今天&#xff0c;微软突然官宣全面开放BingChat&#xff1a; 无需任何等待。只需注册一个账户&#xff0c;首页即可体验。 NewBing最新更新新特性官方文档 https://www.microsoft.com/en-…

ETL 组件Spark资源设置指导

一、概念介绍 1.RDD RDD&#xff08;Resilient Distributed Dataset&#xff09;:弹性分布式数据集&#xff0c;是Spark中最基础的数据抽象。它本质就是一个类&#xff0c;屏蔽了底层对数据的复杂抽象和处理&#xff0c;为用户提供了一组方便数据转换和求值的方法。 简单来说…

研报精选230505

目录 【行业230505国信证券】风电or电网产业链周评&#xff08;4月第5周&#xff09;&#xff1a;海风开发资源集中释放&#xff0c;黑色类原材料价格持续下行 【行业230505天风证券】通信AI系列之&#xff1a;人工智能之火点燃算力需求&#xff0c;AI服务器迎投资机遇 【行业2…

数字孪生遇上VR:未来的新生态

数字孪生和虚拟现实&#xff08;VR&#xff09;是当今技术领域备受关注的两个概念。 数字孪生作为物理世界的数字映像&#xff0c;已经在许多行业得到了广泛应用。而VR则是一种基于计算机生成的三维交互式虚拟环境&#xff0c;被广泛应用于娱乐、教育和游戏等领域。 数字孪生…

十一、MyBatis的逆向工程

文章目录 十一、MyBatis的逆向工程11.1 (清新简洁版)创建逆向工程的步骤11.2 (奢华尊享版)创建逆向工程的步骤11.3 说明尊享版和简洁版的区别 本人其他相关文章链接 十一、MyBatis的逆向工程 正向工程&#xff1a;先创建Java实体类&#xff0c;由框架负责根据实体类生成数据库…

Spring MVC程序开发

文章目录 一、什么是 Spring MVC&#xff08;一&#xff09;MVC的定义&#xff08;二&#xff09;MVC 和 Spring MVC 的关系&#xff08;三&#xff09;为什么要学习 Spring MVC 二、Spring MVC使用方法和技巧&#xff08;一&#xff09;Spring MVC 创建和连接&#xff08;二&a…

clonezilla(再生龙)克隆系统操作

一、前言 背景&#xff1a;由于存在对嵌入式设备系统备份的需求&#xff0c;主要使用在对一个嵌入式设备安装好ros以及其他插件&#xff08;安装时间十分冗长&#xff09;&#xff0c;然后对该系统进行备份&#xff0c;快速复制到下一台嵌入式设备中。因此引出了克隆linux系统…

MySQL知识学习08(MySQL自增主键一定是连续的吗)

众所周知&#xff0c;自增主键可以让聚集索引尽量地保持递增顺序插入&#xff0c;避免了随机查询&#xff0c;从而提高了查询效率。 但实际上&#xff0c;MySQL 的自增主键并不能保证一定是连续递增的。 下面举个例子来看下&#xff0c;如下所示创建一张表&#xff1a; 1、自…

C++类与对象(二)——拷贝构造函数

文章目录 拷贝构造函数1.拷贝构造函数的概念2.拷贝构造函数的特性 前言 本章继续学习类的6个默认成员函数——拷贝构造函数 拷贝构造函数 1.拷贝构造函数的概念 拷贝构造函数&#xff1a;使用已经存在的一个对象初始化创建另一个对象。 举例&#xff1a; class Date { publ…

Golang每日一练(leetDay0056) 单个编辑距离、寻找峰值

目录 161. 单个编辑距离 One Edit Distance &#x1f31f;&#x1f31f; 162. 寻找峰值 Find Peak Element &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 …

vmware 安装Kylin-Desktop-V10-SP1-General-Release-2203-X86_64.iso

下载 官网&#xff1a;国产操作系统、银河麒麟、中标麒麟、开放麒麟、星光麒麟——麒麟软件官方网站 (kylinos.cn) 点击桌面操作系统 选择No1 点击申请试用 填写相关信息&#xff0c;点击立即提交&#xff0c;就会获取到下载连接&#xff0c; 点击下载按钮等待下载完成即可 安…