【数据结构】排序之插入排序

排序目录

  • 1.前言
  • 2. 排序的概念及其运用
    • 2.1 排序的概念
    • 2.2 排序的运用
    • 2.3 常见的排序算法
  • 3. 插入排序
    • 3.1 基本思想
    • 3.2 直接插入排序
      • 3.2.1 直接插入排序实现
        • 3.2.1.1 分析
        • 3.2.1.2 代码实现
    • 3.3 希尔排序
      • 3.3.1 希尔排序实现
        • 3.3.1.1 分析
        • 3.3.1.2 代码实现
  • 4. 附代码
    • 4.1 sort.h
    • 4.2 sort.c
    • 4.3 test.c

1.前言

在生活中处处可见排序,当我们打开京东或者其它购物平台时,搜索物品,它会有一定的排序。
这次就来分享的博客与排序有关。
正文开始。

2. 排序的概念及其运用

2.1 排序的概念

排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。

稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。

内部排序:数据元素全部放在内存中的排序。
外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序。

2.2 排序的运用

举个例子:
在京东上平板的统合排名:
在这里插入图片描述
来看看高校的排名:
在这里插入图片描述
可能每个人搜出来的不一样。

2.3 常见的排序算法

在这里插入图片描述

3. 插入排序

3.1 基本思想

直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。
就像是在玩扑克牌时候,对刚拿的牌来进行一个插入。
在这里插入图片描述

3.2 直接插入排序

当插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i-1]已经排好序,此时用array[i]的排序码与array[i-1],array[i-2],…的排序码顺序进行比较,找到插入位置即将array[i]插入,原来位置上的元素顺序后移。

直接看动图:
在这里插入图片描述
直接插入排序的特性总结:

  1. 元素集合越接近有序,直接插入排序算法的时间效率越高
  2. 时间复杂度:O(N^2)
  3. 空间复杂度:O(1),它是一种稳定的排序算法
  4. 稳定性:稳定

3.2.1 直接插入排序实现

以升序为例子

3.2.1.1 分析

就是把没排好的数插入到已经排好的数中,实现有序。
实现排序,先实现单趟。
假设在一个已经排好序的区间[0,end],然后把end+1位置的值插入进去,那怎么插入呢?
从后往前,依次比较,如果比end+1大,那就往后挪,把位置空出来,再把值放进去。为了记录插入的数据,用一个临时变量tmp存储 end+1的值,避免被覆盖。

在这里插入图片描述
假设前面的已经[0,end],也就是3,4,9已经排好。这时要插入6,先记录一下tmp=6,然后依次往前比较,如果比tmp大,那就往后挪。
在这里插入图片描述
还有一种情况:
一直往走,往后挪数据,当end<0时结束。
在这里插入图片描述
所以这里循环的条件就是while (end >= 0)
如果tmp < a[end],就实现a[end + 1] = a[end],然后end1--
循环结束就有两种情况:一种是tmp>=end,tmp就得放在end后面。另一种是:在while条件结束,出现end<0。
在这里插入图片描述
单趟的已经实现,那怎么实现整体?
while循环外面再套一层循环。
第一个数据就是[0,0],再往下是[0,1],2位置的往前插入。那么它的结束位置就是n-1,不能是n,因为如果到n,那么tmp位置访问n+1,已经越界了。

3.2.1.2 代码实现
void InsertSort(int* a, int n)
{// [0, end] end+1for (int i = 0; i < n - 1; ++i){int end =i;int tmp = a[end + 1];while (end >= 0){if (tmp < a[end]){a[end + 1] = a[end];--end;}else{break;}}a[end + 1] = tmp;}
}

来看看结果:
在这里插入图片描述

3.3 希尔排序

希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成个组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工作。当到达=1时,所有记录在统一组内排好序。
在这里插入图片描述
希尔排序的特性总结:

  1. 希尔排序是对直接插入排序的优化。
  2. 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试的对比。
  3. 希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在好些书中给出的希尔排序的时间复杂度都不固定:
  4. 稳定性:不稳定

3.3.1 希尔排序实现

希尔排序分为两部分:第一部分是预排序,第二部分是直接插入排序。

3.3.1.1 分析

预排序的目的是让数组基本有序,这样直接插入就很快。
举个例子:gap=3
将间隔为3的分为一组,那么总的就分为了三组。红的一组,蓝的一组,绿的一组。
在这里插入图片描述
那么它的预排序怎么实现呢?
就是将分的这三组,分别进行插入排序。
首先将9当成已经排好的数据,那么下一个不是8,而是间隔为3的6,把6往前插入,然后继续找下一个就是4,继续往前面插入。
最后就是这样;
在这里插入图片描述
剩下的两组也是一样的,最终排出来就是
在这里插入图片描述
这里只是接近有序。

就是把上面的直接插入排序的tmp换成end + gap位置的就行。
在这里插入图片描述
假设先对红色这组经行排序,那就是:
在这里插入图片描述
注意循环的条件如果是i<n,那么就会访问越界,注意看图上,发现结束的位置就是n-gap。
如果排实现的两组,那么就直接再套一层,循环gap=3次就排完了。
在这里插入图片描述
这里套了三层排序,也只是预排序,j为0就是红色的一组,j为1就是蓝色那组,j为2就是绿色那一组。
在这里插入图片描述
优化一下,实现多组并排,之间是一组一组往后排,现在是直接在gap组之间来回跳,第一次排红色,第二次排蓝色,第三次排绿色。
少一层循环。
在这里插入图片描述
gap怎么选择:
在这里插入图片描述

《数据结构(C语言版)》— 严蔚敏
在这里插入图片描述

《数据结构-用面相对象方法与C++描述》— 殷人昆
在这里插入图片描述

在这里插入图片描述
所以这里实现希尔排序,就是将gap不断变小,
gap > 1时是预排序,目的让他接近有序,而gap == 1是直接插入排序,目的是让他有序。
那么这里gap怎么选择呢?
如果gap = gap / 2,这里跳跃就比较小,所以选择gap = gap / 3 ,但为了保证最后一次为1,这里就得加1,也就是gap = gap / 3 + 1。
在这里插入图片描述
来看看结果:
在这里插入图片描述

3.3.1.2 代码实现
void ShellSort(int* a, int n)
{int gap = n;// gap > 1时是预排序,目的让他接近有序// gap == 1是直接插入排序,目的是让他有序while (gap > 1){//gap = gap / 2;gap = gap / 3 + 1;for (int i = 0; i < n - gap; ++i){int end = i;int tmp = a[end + gap];while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];end -= gap;}else{break;}}a[end + gap] = tmp;}}
}

4. 附代码

4.1 sort.h

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
#include<time.h>void PrintArray(int* a, int n);
void InsertSort(int* a, int n);
void ShellSort(int* a, int n);

4.2 sort.c

#include"Sort.h"void PrintArray(int* a, int n)
{for (int i = 0; i < n; i++){printf("%d ", a[i]);}printf("\n");
}// 时间复杂度:O(N^2) 逆序
// 最好的情况:O(N)  顺序有序
void InsertSort(int* a, int n)
{// [0, end] end+1for (int i = 0; i < n - 1; ++i){int end =i;int tmp = a[end + 1];while (end >= 0){if (tmp < a[end]){a[end + 1] = a[end];--end;}else{break;}}a[end + 1] = tmp;}
}// 平均O(N^1.3)
void ShellSort(int* a, int n)
{int gap = n;// gap > 1时是预排序,目的让他接近有序// gap == 1是直接插入排序,目的是让他有序while (gap > 1){//gap = gap / 2;gap = gap / 3 + 1;for (int i = 0; i < n - gap; ++i){int end = i;int tmp = a[end + gap];while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];end -= gap;}else{break;}}a[end + gap] = tmp;}}/*for (int j = 0; j < gap; ++j){for (int i = j; i < n-gap; i += gap){int end = i;int tmp = a[end + gap];while (end >= 0){if (tmp < a[end]){a[end + gap] = a[end];end -= gap;}else{break;}}a[end + gap] = tmp;}}*/
}

4.3 test.c

#include"Sort.h"void TestInsertSort()
{int a[] = { 3, 2, 6, 8, 4, 6, 0, 9, 5, 7, 1 };InsertSort(a, sizeof(a) / sizeof(int));PrintArray(a, sizeof(a) / sizeof(int));
}void TestShellSort()
{int a[] = { 3, 2, 6, 8, 4, 6, 0, 9, 5, 7, 1 };ShellSort(a, sizeof(a) / sizeof(int));PrintArray(a, sizeof(a) / sizeof(int));
}
int main()
{TestInsertSort();	TestShellSort();return 0;
}

在之后的博客中会继续分享与排序有关的内容,请多多关注。
有问题请指出,大家一起进步!

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

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

相关文章

Lumerical------按键中断程序执行

Lumerical------中断程序执行 引言正文 引言 在 Lumerical 中&#xff0c;很多时候我们需要通过 sweep 的方式来获取我们想要的结果&#xff0c;然而&#xff0c;有时候当我们运行程序后发现书写的脚本有问题时&#xff0c;我们想要强行终止程序的执行&#xff0c;该怎么办呢&…

K8s攻击案例:组件未授权访问导致集群入侵

K8s集群往往会因为组件的不安全配置存在未授权访问的情况&#xff0c;如果攻击者能够进行未授权访问&#xff0c;可能导致集群节点遭受入侵。比较常见的的组件未授权访问漏洞&#xff0c;主要包括 API Server 未授权访问、kubelet 未授权访问、etcd 未授权访问、kube-proxy 不安…

C++系列-第1章顺序结构-4-整型int

C系列-第1章顺序结构-4-整型int 在线练习&#xff1a; http://noi.openjudge.cn/ https://www.luogu.com.cn/ 总结 本文是C系列博客&#xff0c;主要讲述整型int的用法 整型int 在C中&#xff0c;int 是一个关键字&#xff0c;用于声明整型变量。int 类型用于存储整数&…

01的token的年度总结

​ 大家好&#xff0c;我是token&#xff0c;一个热爱.NET的普通人&#xff0c;同样我来自湖南衡阳&#xff0c;再次之前我已经遇到非常多的湖南衡阳的老乡&#xff0c;比如李哥。 ​ 在这里一年中&#xff0c;我的成长也是非常迅速的&#xff0c;每一年的的每一天&#xff0c…

【Linux】深挖进程地址空间

> 作者简介&#xff1a;დ旧言~&#xff0c;目前大二&#xff0c;现在学习Java&#xff0c;c&#xff0c;c&#xff0c;Python等 > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;熟悉【Linux】进程地址空间 > 毒鸡汤&#xff…

Thinkphp+vue+mysql学生作业管理系统21j0r

运行环境:phpstudy/wamp/xammp等 开发语言&#xff1a;php 后端框架&#xff1a;Thinkphp5 前端框架&#xff1a;vue.js 服务器&#xff1a;apache 数据库&#xff1a;mysql 数据库工具&#xff1a;Navicat/phpmyadmin 为设计一个安全便捷&#xff0c;并且使用户更好获取本学院…

解决jenkins、git拉取代码仓库失败Please make sure you have the correct access rights

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a; https://gitee.com/nbacheng/n…

Redis主从

一、为何需要主从 单节点Redis的并发能力是有上限的&#xff0c;要进一步提高Redis的并发能力&#xff0c;就需要搭建主从集群&#xff0c;实现读写分离 二、如何设置主从 有临时和永久两种模式&#xff1a; 修改配置文件&#xff08;永久生效&#xff09; 在redis.conf中添…

【23.12.29期--Spring篇】Spring的 IOC 介绍

介绍一下Spring的IOC ✔️引言✔️ lOC的优点✔️Spring的IOC✔️ 拓展知识仓✔️IOC是如何实现的&#xff1f; ✔️引言 所谓的IOC (inversion of control) &#xff0c;就是控制反转的意思。何为控制反转? 在传统的程序设计中&#xff0c;应用程序代码通常控制着对象的创建和…

Typora使用PicGo+Gitee上传图片

Typora使用PicGoGitee上传图片 1.下载PicGo(国内镜像) https://mirrors.sdu.edu.cn/github-release/Molunerfinn_PicGo/ 点击PicGo-Setup-2.3.0-x64.exe &#xff08;64位安装&#xff09; 然后打开gitee&#xff08;没注册先注册&#xff09; 2.下载node.js插件 https:/…

Android Camera

1. 相关的API Android有三套关于摄像头的API(库)&#xff0c;分别是Camera、Camera2和CameraX&#xff0c;其中Camera已废弃&#xff0c;在Android5.0以后推荐使用Camera2和CameraX&#xff0c;Camera2推出是用来替换Camera的&#xff0c;它拥有丰富的API可以为复杂的用例提供…

算法与数据结构--二叉搜索树与自平衡二叉搜索树

0.字典&#xff08;即c的map&#xff09; 注&#xff1a;字典的 "member运算" 指的是检查字典中是否存在某个特定的键的操作&#xff0c;即查询操作。 如果我们使用数组来实现字典/map&#xff0c;虽然使用二分法查询也可以达到logn&#xff0c;但是的话插入和删除太…

SourceTree的安装和使用

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、安装&#xff1a;二、使用步骤1.获取地址2.放入sourceTree 3.点击推送 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 简单讲解一…

XV7001BB陀螺传感器

XV7001BB是一款工业级的高精度角度测量仪器&#xff0c;具备SPI或i2c串行接口&#xff0c;能够输出16位的角速率数据。同时&#xff0c;内置温度传感器可以实时监测环境温度&#xff0c;可选数字滤波器可以有效降低噪声干扰&#xff0c;使得测量结果更加准确可靠。作为一款低功…

Apache OFBiz 远程代码执行漏洞(CVE-2023-51467)

产品简介 Apache OFBiz是一个电子商务平台&#xff0c;用于构建大中型企业级、跨平台、跨数据库、跨应用服务器的多层、分布式电子商务类应用系统。 漏洞概述 该系统的身份验证机制存在缺陷&#xff0c;可能允许未授权用户通过绕过标准登录流程来获取后台访问权限。此外&…

Visual Studio Code 中,通过显示波浪线来提示代码中存在的错误或警告

在Visual Studio Code (VSCode)中&#xff0c;编辑器会通过显示波浪线&#xff08;也称为squiggles&#xff09;来提示代码中存在的错误或警告。这些波浪线的颜色通常为红色表示错误&#xff0c;黄色表示警告。 1. 自定义错误和警告提示 • 打开设置&#xff1a;点击左上角菜单…

WebService

调试工具&#xff1a;Postman、SoapUI Soap WebService :.net WCF 、Java CFX WebService三要素&#xff1a; SOAP&#xff08;Simple Object Access Protocol&#xff09;&#xff1a;用来描述传递信息的格式&#xff0c; 可以和现存的许多因特网协议和格式结合使用&#x…

了解英语中主语谓语宾语等等句子成分

目录 官方书面解释&#xff1a; 简介&#xff1a; 细分&#xff1a; 通俗易懂解释&#xff1a; 各个成分的解释&#xff1a; 扩展资料&#xff1a; 官方书面解释&#xff1a; 简介&#xff1a; 在句子中&#xff0c;词与词之间有一定的组合关系&#xff0c;按照不同的…

三分钟学完科研论文常用统计图

统计分析的结果通常包括统计图和统计表。统计图是一种用图形表示数据的方式&#xff0c;它能够直观地展示数据的分布、趋势和关系。科研论文中常见的统计图包括条形图、饼图、折线图、散点图等。这些图形可以帮助人们快速地理解和分析数据&#xff0c;找出其中的规律和特征。今…

赛宁综合安全验证评估,筑牢关基网络安全屏障

在国际复杂态势和数字经济发展的驱动下&#xff0c;关键信息基础设施&#xff08;以下简称&#xff1a;关基&#xff09;的安全运营逐步走向实战化、体系化和常态化。验证评估作为安全运营的试金石&#xff0c;已成为实现动态防御、主动防御的有力手段。如何通过体系化验证评估…