【排序算法】二、希尔排序(C/C++)

「前言」文章内容是排序算法之希尔排序的讲解。(所有文章已经分类好,放心食用)

「归属专栏」排序算法

「主页链接」个人主页

「笔者」枫叶先生(fy)

目录

  • 希尔排序
    • 1.1 原理
    • 1.2 代码实现(C/C++)
    • 1.3 特性总结

希尔排序

1.1 原理

希尔排序是一种基于直接插入排序的排序算法,也称为“缩小增量排序”

希尔排序法的基本思想是:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录"基本有序"时,再对全体记录进行一次直接插入排序

希尔排序:基于数组(顺序表)的结构进行排序

希尔排序的由来

希尔排序是按其设计者希尔的名字命名的

他对普直接入排序的时间复杂度进行分析,得出了以下结论:

  1. 直接插入排序的时间复杂度最坏情况下为O(N^2),此时待排序列为逆序,或者说接近逆序
  2. 直接插入排序的时间复杂度最好情况下为O(N),此时待排序列为升序,或者说接近升序

于是希尔就想:若是能先将待排序列进行一次预排序,使待排序列接近有序(接近我们想要的顺序),然后再对该序列进行一次直接插入排序,此时已经排好序了,并且时间复杂度也降低了

希尔排序 = 预排序 + 一次直接插入排序

因为此时直接插入排序的时间复杂度为O(N)(直接插入排序对排序的数组接近有序的时候,时间复杂度为O(1)),那么只要控制预排序阶段的时间复杂度不超过O(^2),那么整体的时间复杂度就比直接插入排序的时间复杂度低了

希尔排序的步骤如下:

  1. 首先选择一个增量序列,通常选择增量序列gap为n/2,n/4,n/8...1,其中n为数组的长度
  2. 根据增量序列将数组分成若干个子序列,对每个子序列进行插入排序
  3. 逐渐缩小增量序列,重复步骤2,直到增量为1,即对整个数组进行一次插入排序

例如,对该数组使用希尔排序进行排序(升序)
在这里插入图片描述

取第一次增量gap为:gap = 10/2,10为数组大小,此时相隔距离为5的元素被分为一组(共分了5组,每组有2个元素),然后分别对每一组进行直接插入排序
在这里插入图片描述
取第二次增量gap为:gap = 5/2,5为第一次增量值,此时相隔距离为2的元素被分为一组(共分了2组,每组有5个元素),然后再分别对每一组进行直接插入排序
在这里插入图片描述
取第三次增量gap为:gap = 2/2,2为第二次增量值,此时gap为1,即整个序列被分为一组,进行一次直接插入排序(对整个数组)
在这里插入图片描述
动图演示如下:
在这里插入图片描述

为什么要让gap由大到小?

  • gap越大,数据挪动得越快;gap越小,数据挪动得越慢
  • 前期让gap较大,可以让数据更快得移动到自己对应的位置附近,减少挪动次数

:一般情况下,取序列的一半作为增量,然后依次减半,直到增量为1(也可自己设置)

希尔排序的时空复杂度

希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在不同的书中给出的希尔排序的时间复杂度都不固定
在这里插入图片描述
在这里插入图片描述
Knuth序列是一种希尔排序中常用的增量序列,由Donald Knuth提出。Knuth序列的计算公式为:h = 3h + 1,其中h是增量序列的值,下面代码gap使用这个公式(有兴趣自己了解)

Knuth进行了大量的试验统计,暂时就按照:O(N^1.25)O(1.6 * N^1.25)来算,按O(N^1.3)计算(最好情况下)

  • 希尔排序时间复杂度O(N*logN) ~ O(N^2),以2为底,最好O(N^1.3),最坏 O(N^2)
  • 希尔排序空间复杂度O(1)

1.2 代码实现(C/C++)

C语言代码如下:(升序)

// 希尔排序(基于直接插入排序)
void ShellSort(int* arr, int n) // arr:需要排序的数组; n:数组的大小
{int gap = n;while (gap > 1){// gap 大于 1, 进行预排序// gap == 1, 相当于直接插入排序(注:循环进来 gap 经过 gap = gap / 3 + 1 这才变成 1 )gap = gap / 3 + 1;for (int i = 0; i < n - gap; ++i){int end = i; // 记录有序列的最后一个下标int tmp = arr[end + gap]; // 保存等待插入的值while (end >= 0){if (arr[end] > tmp) // arr[end]比要插入的数大,向后移动{arr[end + gap] = arr[end]; // 向后移,进行覆盖,tmp已经保存被覆盖的值end -= gap;}else // arr[end]比要插入的数小,已有序,跳出循环{break; }}arr[end + gap] = tmp; // 进行插入}}
}

C++代码:(升序)

// 希尔排序(基于直接插入排序)
void ShellSort(vector<int>& arr)
{int n = arr.size();int gap = n;while (gap > 1){// gap 大于 1, 进行预排序// gap == 1, 相当于直接插入排序(注:循环进来 gap 经过 gap = gap / 3 + 1 这才变成 1 )gap = gap / 3 + 1;for (int i = 0; i < n - gap; ++i){int end = i; // 记录有序列的最后一个下标int tmp = arr[end + gap]; // 保存等待插入的值while (end >= 0){if (arr[end] > tmp) // arr[end]比要插入的数大,向后移动{arr[end + gap] = arr[end]; // 向后移,进行覆盖,tmp已经保存被覆盖的值end -= gap;}else // arr[end]比要插入的数小,已有序,跳出循环{break;}}arr[end + gap] = tmp; // 进行插入}}
}

1.3 特性总结

希尔排序的特性总结

  • 希尔排序是对直接插入排序的优化
  • gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。整体而言,可以达到优化的效果
  • 希尔排序时间复杂度O(N*logN) ~ O(N^2),以2为底
  • 空间复杂度O(1)
  • 稳定性:不稳定

--------------------- END ----------------------

「 作者 」 枫叶先生
「 更新 」 2024.1.9
「 声明 」 余之才疏学浅,故所撰文疏漏难免,或有谬误或不准确之处,敬请读者批评指正。

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

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

相关文章

数据结构-测试1

一、判断题 1.队列中允许插入的一端叫队头&#xff0c;允许删除的一端叫队尾&#xff08;F&#xff09; 队列中允许删除的一端叫队头&#xff08;front&#xff09;,允许插入的一端叫队尾&#xff08;rear&#xff09; 2. 完全二叉树中&#xff0c;若一个结点没有左孩子&#…

Developer Tools for Game Creator 1

插件包含: 持久世界时间管理系统 单击以生成对象或预设 游戏内调试控制台 游戏内事件控制台 控制台管理控制 命令模板脚本 游戏内屏幕截图 低分辨率和高分辨率图像 缩略图生成 移动支持 使用Game Creator Action或拖放来激活和控制组件,无需编码。 通过此资产,您可以获得: …

初识 Elasticsearch 应用知识,一文读懂 Elasticsearch 知识文集(1)

文章目录 &#x1f3c6; 初识 Elasticsearch 应用知识&#x1f50e; 初识 Elasticsearch 应用知识(1)&#x1f341;&#x1f341; 01、什么是 Elasticsearch&#xff1f;&#x1f341;&#x1f341; 02、能列出 10 个使用 Elasticsearch 作为其搜索引擎或数据库的公司吗&#x…

2023 年度合辑 | 出海大年的全球化产品洞察和服务动向

2023 年度合辑 年度关键词 出海&全球化 出海 & 全球化通信服务全面升维 出海大年&#xff0c;融云全球互联网通信云作为“全球化最佳基础设施”之一&#xff0c;发挥技术沉淀和实践积累带来的核心优势&#xff0c;结合市场变化对出海 & 全球化通信服务进行了全方位…

李沐之神经网络基础

目录 1.模型构造 1.1层和块 1.2自定义块 1.3顺序块 1.4在前向传播函数中执行代码 2.参数管理 2.1参数访问 2.2参数初始化 3.自定义层 3.1不带参数的层 3.2带参数的层 4.读写文件 4.1加载和保存张量 4.2加载和保存模型参数 1.模型构造 1.1层和块 import torch fr…

c JPEG编码,但有错误

#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdlib.h> #include <unistd.h> #include <sys/ioctl.h> #include <linux/videodev2.h> //v4l2 头文件 #include <strin…

MySQL之数据的导入、导出远程备份

目录 一. navicat的导入、导出 1.1 导入 1.2 导出 二. mysqldump命令导入、导出 2.1 导出 2.2 导入 三. LOAD DATA INFILE 命令导入、导出 3.1 设置 3.2 导出 3.3 导入 3.4 查看secure_file_priv设置 四. 远程备份 4.1 导出 4.2 导入 五. 思维导图 一. navicat的导入、导…

互联网云计算:开启未来智能生活的新篇章

互联网每天新进程&#xff0c;科技还得看啊浩说。 在互联网技术的飞速发展中&#xff0c;云计算已经成为了我们生活中不可或缺的一部分。它像一座神奇的云端宝库&#xff0c;为我们提供了无尽的计算资源和存储空间。让我们一起来探索互联网云计算的奥秘和魅力。 一、云计算&am…

Java多线程-Thread类的run方法

Java多线程-Thread类的run方法 一、背景二、研究Thread类的start()源码1、源码&#xff08;比较短&#xff0c;贴一下&#xff09;1.1 重点&#xff1a;start0(); 三、研究Thread类的run()源码1、源码&#xff08;很关键&#xff0c;必须贴&#xff09; 四、创建线程的2种方式1…

图灵机原理

图灵机原理 组成 一个两头无延伸的纸带&#xff0c;一个读写头&#xff0c;一本操作手册。 格式 纸带上只能写 0 和 1。 读写头可以在纸带上左右移动。 手册的每一页都有“一个判断”和“三个操作”&#xff1a; 一个判断&#xff1a;判断读写头当前位置的值是 0 还是 1&…

实习面试经历(微软/360/蔚来/百度/小米/元戎启行/腾讯)

从去年十一月到现在陆陆续续面试了好几家公司实习&#xff0c;做个简单的记录供大家参考吧&#xff0c;个人背景是某211大三的科班&#xff0c;之前没有实习经历 按照时间线&#xff1a; 11.8 微软Azure工程实习生 这是我第一次面试实习&#xff0c;个人觉得答的很不好。之前…

淘宝/天猫商品详情实时数据API技术实现

随着电子商务的蓬勃发展&#xff0c;对于电商平台的商家而言&#xff0c;实时获取商品数据变得至关重要。通过API接口&#xff0c;可以轻松地从电商平台获取这些数据。本文将详细介绍如何使用淘宝/天猫提供的API接口实现商品详情数据的实时获取&#xff0c;并给出具体的代码示例…

podman configure insecure certificate registry【podman 设置非安全镜像仓库】

预备条件 docker registry仓库私搭并配置证书centos 7.9 部署 harbor 镜像仓库实践harbor 部署入门指南Podman 部署私有镜像仓库 设置 $ vim /etc/hosts 192.168.23.47 registry.ghostwritten.com$ vim /etc/containers/registries.conf ... [[registry]] location "r…

【css技巧】css设置文字不能被选中

ChatGPT4.0国内站点&#xff1a;海鲸AI 在CSS中&#xff0c;如果你想让文本内容不能被用户选中&#xff0c;可以使用user-select属性。这个属性可以控制用户是否能够选择文本。以下是如何使用这个属性的例子&#xff1a; .unselectable {-webkit-user-select: none; /* Safar…

7.2 1D PARALLEL CONVOLUTION—A BASIC ALGORITHM

正如我们在第7.1节中提到的&#xff0c;所有输出&#xff08;P&#xff09;元素的计算可以在卷积中并行完成。这使得卷积成为并行计算的理想问题。根据我们在矩阵-矩阵乘法方面的经验&#xff0c;我们可以快速编写一个简单的并行卷积内核。为了简单起见&#xff0c;我们将从1D卷…

【MySQL】数据库概述与SQL语句

一、数据库基本概念 数据库&#xff1a;DateBase&#xff0c;简称&#xff1a;DB 数据库特点&#xff1a; 持久化存储数据 -> 文件系统方便存储和管理数据使用了统一方式管理数据库 -> SQL 常见的数据库软件&#xff1a; OracleMySQLMicrosoft SQL ServerDB2SQLite …

【liunx】线程池+单例模式+STL,智能指针和线程安全+其他常见的各种锁+读者写者问题

线程池单例模式STL,智能指针和线程安全其他常见的各种锁读者写者问题 1.线程池2.线程安全的单例模式3.STL,智能指针和线程安全4.其他常见的各种锁4.读者写者问题 喜欢的点赞&#xff0c;收藏&#xff0c;关注一下把&#xff01; 1.线程池 目前我们学了挂起等待锁、条件变量、信…

【排序算法】一、排序概念和直接插入排序(C/C++)

「前言」文章内容是排序算法之直接插入排序的讲解。&#xff08;所有文章已经分类好&#xff0c;放心食用&#xff09; 「归属专栏」排序算法 「主页链接」个人主页 「笔者」枫叶先生(fy) 目录 一、排序概念的介绍二、直接插入排序2.1 原理2.2 代码实现&#xff08;C/C&#xf…

Web API乐观锁和悲观锁

在 Web API 中&#xff0c;乐观锁&#xff08;Optimistic Locking&#xff09;和悲观锁&#xff08;Pessimistic Locking&#xff09;是两种常见的并发控制机制。它们的目的都是在多个用户同时访问和修改相同资源时&#xff0c;确保数据的一致性和完整性。 乐观锁 乐观锁的思…

Linux的网络设置

一.查看网络配置 1.查看网络接口信息 - ifconfig ① 直接使用 ifconfig 命令 默认显示活动的网卡 解析&#xff1a; ② ifconfig 具体网卡名称 只显示具体的网卡的信息 ③ ifconfig -a 显示所有的网卡 ④ ifconfig 网卡名称 down 关闭网卡 ifdown 关闭网卡 …