八大排序算法(C语言版)之插入排序

news2025/4/17 1:11:59

八大排序详解

  • 目录:
  • 一、排序的概念
    • 1.1 排序的概念
    • 1.2 排序的应用
  • 二、直接插入排序
  • 三、希尔排序
  • 四、排序算法复杂度及稳定性分析

目录:

八大排序算法:

八大排序算法
插入排序
选择排序
交换排序
归并排序
非比较排序
直接插入排序
希尔排序
选择排序
堆排序
冒泡排序
快速排序
归并排序
计数排序

超链接:
插入排序
选择排序
交换排序
归并排序
非比较排序

一、排序的概念

1.1 排序的概念

排序:所谓排序,就是使一串记录, 按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j], 且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。
内部排序:数据元素全部放在内存中的排序。
外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序。

1.2 排序的应用

排序的目的通常是为了方便查找,或者统计最多或者最少的重复次数。
1.游戏竞赛。 游戏规则是随机一组30张图片,要求参加比赛的10人在30秒之内把图片按照从小到大顺序排序,时间最少的获胜。
2.调查问卷。 在1~10000中随机生成N个数,对于重复的数只保留一个,不同的数对应着不同学生的学号,再把这些数从小到大排序,按顺序找同学调查。
3.颁发特等奖学金。 某个大学有n名学生,每个人都有m门课,按照综合成绩排名,需要挑出最优秀的k位学生颁发特等奖学金。

二、直接插入排序

直接插入排序的基本思想:
把待排序的内容记录并逐一与排序好的有序序列比较,插入到有序序列中,直到待排序列的记录全部插入完毕,得到一个新的有序序列,这就是直接插入排序
在这里插入图片描述
代码如下

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <time.h>
#include <windows.h>
#define m 1000
void IsertSort(int* arr, int n)
{
    int i;
    for (i = 1; i < n; i++)//i为待排序的第一个数下标
    {
        int end = i - 1;//end 为已排好序列的尾下标
        int tmp = arr[i];//把待排序的第一个数存起来
        //遍历已排序列,进行比较然后插入,这里我进行从小到大排序
        while (end >= 0)
        {
            if (arr[end] > tmp)//如果前面的数大,就把他往后移动一个
            {
                arr[end + 1] = arr[end];
                end--;
            }
            //否则就跳出
            else
                break;
            arr[end + 1] = tmp;
        }
    }
    //打印排序后的数据
    for (i = 0; i < n; i++)
    {
        printf("%d ", arr[i]);
    }
}
int main()
{
    int head, end,arr[m];
    //srand(初始化时间),time(直接返回时间戳)
    srand((unsigned)time(NULL));

    head = clock();
    for (int i = 0; i < m; i++)
        arr[i] = rand();//,时间不停的变化,每次产生不同的随机值
    IsertSort(arr,sizeof(arr)/sizeof(arr[0]));
    end = clock();
    //排序需要花费的时间
    printf("\n%d\n ", end - head);
    return 0;
}

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

三、希尔排序

希尔排序又叫缩小增量法。
希尔排序的基本思想:
先选定一个整数,然后把待排序的记录分成这个整数的组,所有距离为这个整数的记录被分在同一个组,并对每一个组内的记录进行排序。先预排序,然后在插入排序。

在这里插入图片描述
代码如下:

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <Windows.h>
#define m 10000
SheelSort(int* arr, int n)
{
  int gap = 3;
    //多趟
 for(int j=0;j<gap; j++)
     //每组进行插入排序
        for (int i =j; i < n - gap; i += gap)
        {
            //单趟
            int end = i;
            int tmp = arr[end + gap];
            while (end >= 0)
            {
                if (arr[end] < tmp)//从大到小排序
                {
                    arr[end + gap] = arr[end];
                    end -= gap;
                }
                else
                    break;   
            }
            arr[end + gap] = tmp;
        }
}
int main()
{
    int head, tail, i;
    int arr[m] = {0};
    srand((unsigned)time(NULL));
    
    for (i = 0; i < m; i++)
        arr[i] = rand()%1000;
    head = clock();
    SheelSort(arr, sizeof(arr) / sizeof(arr[0]));
    tail = clock();
    printf("%d ", tail - head);

    return 0;
}

效率如下
在这里插入图片描述
我们可以优化一下(减少一个循环,但是效率还是差不多得,而且代码更简洁):

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <Windows.h>
#define m 10000
SheelSort_1(int* arr, int n)
{
    int gap = 3;
        //按顺序,一组一组排序
        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 + gap] = arr[end];
                    end -= gap;
                }
                else
                    break;
            }
            arr[end + gap] = tmp;
        }
}
int main()
{
    int head, tail, i;
    int arr[m] = {0};
    srand((unsigned)time(NULL));
    
    for (i = 0; i < m; i++)
        arr[i] = rand()%1000;
    head = clock();
    SheelSort_1(arr, sizeof(arr) / sizeof(arr[0]));
    tail = clock();
    printf("%d ", tail - head);

    return 0;
}

在这里插入图片描述
我们可以得知预排序的意义
1.gap越大,大的数可以更快的到后面,小的数可以更快到前面,gap越大跳的越快,越不接近有序。
2.gap越小,大的小的数挪动越慢,越接近有序。
3.gap= =1,就是直接插入排序。
但是我们不知道gap取什么值最好
我们在把代码变一变,让gap无论是多少,最后都等于gap= =1.(gap >1为预排序)

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <Windows.h>
#define m 10000
SheelSort_3(int* arr, int n)
{
    int gap = n;
    while(gap >1)//先预排序,预排序结束后,直接插入排序
    {
    gap=gap/3+1;
    //gap=gap/2;
        //按顺序,一组一组排序
        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 + gap] = arr[end];
                    end -= gap;
                }
                else
                    break;
            }
            arr[end + gap] = tmp;
        }
        }
}
int main()
{
    int head, tail, i;
    int arr[m] = {0};
    srand((unsigned)time(NULL));
    
    for (i = 0; i < m; i++)
        arr[i] = rand()%1000;
    head = clock();
    SheelSort_3(arr, sizeof(arr) / sizeof(arr[0]));
    tail = clock();
    printf("%d ", tail - head);

    return 0;
}

计算它的时间复杂度?

1.gap很大时gap=n / 3+1,可分为n/3组数据,每组3个元素,每组最坏的比较次数为3次所以一共:n / 3 * 3次。
2.gap很小时,gap=1,每组1个元素,很接近有序,间距为gap的这些数据,数据往后挪动的次数:n。
3.gap很大时,n / 9个组,9个元素,每组最坏比较36次。(1+2……+8),间距为gap的这些数据。合计挪动数据:n / 9* 36=4n次
4.外面那个循环运算了log3^N次
总结:合计n / gap组,每组gap个,每组插入:1+2+3+……+gap。合计:(1+gap) * gap / 2
时间复杂度O(N^1.3)最好情况

稳定性:不稳定

四、排序算法复杂度及稳定性分析

如图:
在这里插入图片描述
表格:
在这里插入图片描述

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

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

相关文章

Win安装protobuf和IDEA使用protobuf插件

一、Win安装protobuf 1、下载编译器 protobuf下载地址&#xff1a;https://github.com/protocolbuffers/protobuf/releases 选择自己需要的版本下载&#xff0c;这里下载的是 protoc-3.19.1-win64.zip&#xff0c;下载之后进行解压即可。 2、配置环境变量 path 系统变量中添加…

用IntelliJ远程打断点调试

前提当然是本地和远程部署的代码一样。 记录下步骤&#xff1a; 1&#xff0c;用token登录kuboard&#xff0c;找到目标容器的IP&#xff1a; 2, 用上一步找到的IP等信息创建Remote JVM Debug: 3&#xff0c;打断点&#xff0c;wkb说要把断点此属性改为线程。我试了下似乎…

menuconfig 图形化配置原理说明二

一. 简介 之前一篇文章中&#xff0c;我们已经知道&#xff1a; scripts/kconfig/mconf 会调用 uboot 根目录下的 Kconfig 文件开始 构建图形化配置界面。 接下来简单学习一下 Kconfig 的语法。因为后面学习 Linux 驱动开发 时&#xff0c;可能会涉及到修改 Kconfig…

VNC图形化远程连接Ubuntu服务器

我的Ubuntu版本22.04.3&#xff0c;带有gnome图形桌面。配置过程参考了几篇博客&#xff0c;大致流程如下。因为是配置完之后才整理的流程&#xff0c;可能有疏漏。 Ubuntu服务器上的配置 1.先在服务器上下载vnc server&#xff08;任何一种版本均可&#xff09; vncserver有…

最近面试遇到的高频面试题

大家好&#xff0c;我是 jonssonyan 互联网寒冬&#xff1f;金九银十真的不存在了么&#xff1f;虽说现在行情是差了一些&#xff0c;面试机会少了一些&#xff0c;但是大部分公司还是或多或少的招人&#xff0c;春招秋招都在进行。有人离职就有人入职。所以如果你还没约到面试…

【vue会员管理系统】篇三之自定义Axios、初试后台接口、跨域问题

一、自定义封装Axios异步对象和添加拦截器 因为本项目很多组件需要通过Axios发送一步请求&#xff0c;所以封装Axios对象&#xff0c;自己封装的Axios在后续可以使用axios中提供的拦截器。 1.在src文件夹下创建utils文件夹&#xff0c;再在utils文件夹下创建request.js文件 2.…

Rabbitmq----分布式场景下的应用

服务异步通信-分布式场景下的应用 如果单机模式忘记也可以看看这个快速回顾rabbitmq,在做学习 消息队列在使用过程中&#xff0c;面临着很多实际问题需要思考&#xff1a; 1.消息可靠性 消息从发送&#xff0c;到消费者接收&#xff0c;会经理多个过程&#xff1a; 其中的每一…

安美数字酒店宽带运营系统 server_ping.php 远程命令执行漏洞

数字于2006年正式推出了中国酒店智慧客房投资运营的相关业务和商业模式,凭借雄厚的研发实力、超前的技术优势、高效整合的精英团队以及深厚的行业积淀,快速地占领了酒店行业智能化服务市场;同时依托自主创新的InnFor Anymode核心技术,创建了全高清酒店客房互动信息服务运营平台…

写新闻稿的基本步骤有哪些?纯干货!

新闻稿作为企业和品牌传递信息的重要载体&#xff0c;不仅要求准确、客观&#xff0c;还应该要具备吸引人的特质。本文伯乐网络传媒将为您详细解析写新闻稿的基本步骤&#xff0c;帮助您轻松撰写出高质量、具有深度的新闻稿。 一、选定热门话题&#xff1a;寻找具有吸引力的爆点…

openwrt下游设备在校园网(DLUT-LingShui)中使用ipv6网络

背景&#xff1a;校园网最多支持6台设备的无感认证&#xff0c;需要使用路由器(本人使用openwrt系统)为更多的设备提供网络&#xff0c;但校园网分配的ipv6地址子网为/128&#xff0c;不能为路由器下的设备分配全球ipv6地址&#xff0c;因此需要使用nat6转发下游设备的局域网ip…

[FSCTF 2023] web题解

文章目录 源码&#xff01;启动!webshell是啥捏细狗2.0ez_php1Hello,youEZ_eval 源码&#xff01;启动! 打开题目&#xff0c;发现右键被禁了 直接ctrlu查看源码得到flag webshell是啥捏 源码 <?php highlight_file(__FILE__); $&#x1f600;"a"; $&#x…

[UDS] --- UDS概述

UDS&#xff08;Unified Diagnostic Services&#xff0c;统一的诊断服务&#xff09;诊断协议是在汽车电子ECU环境下的一种诊断通信协议&#xff0c;在ISO 14229中规定。它是从ISO 14230-3&#xff08;KWP2000&#xff09;和ISO 15765-3协议衍生出来的。“统一”这个词意味着它…

web - Tomcat服务器

文章目录 目录 文章目录 前言 一 . CS和BS的异同 二 . 什么是Tomcat 二 . Tomcat安装 四 . Tomcat目录结构 bin目录: 用于存放二进制的可执行文件 config目录 server.xml&#xff1a;配置整个服务器信息。例如修改端口号。默认HTTP请求的端口号是&#xff1a;8080 lib目录 log…

Qwt QwtPlotGrid网格类详解

1.概述 QwtPlotGrid类是Qwt绘图库中用于绘制网格的类。网格是图表中用于显示坐标轴刻度之间的辅助线的一种视觉元素。使用QwtPlotGrid类可以方便地添加水平和垂直网格线到绘图区域上。 以下是类继承关系图&#xff1a; 2.常用接口 分别启用或禁用x和y轴上的网格线。 enable…

优化改进YOLOv5算法:加入ODConv+ConvNeXt提升小目标检测能力——(超详细)

为了提升无人机视角下目标检测效果,基于YOLOv5算法,在YOLOv5主干中实现了Omnidimensional Convolution(ODConv),以在不增加网络宽度和深度的情况下提高精度,还在YOLOv5骨干网中用ConvNeXt块替换了原始的C3块,以加快检测速度。 1 Omni-dimensional dynamic convolution …

Docker 容器服务的注册、发现及Docker安全

目录 Docker容器服务的注册和发现 1、什么是服务注册与发现&#xff1f; 2、什么是consul consul的部署 1、环境准备 2、部署consul服务器 1&#xff09;建立 Consul 服务 2&#xff09;设置代理&#xff0c;在后台启动 consul 服务端 3&#xff09;查看集群信息 4&a…

VSCode:清理ipch缓存

VSCode使用了一段时间&#xff0c;发现有些变慢&#xff0c;电脑管家扫描后&#xff0c;提示“AppData\Local\Microsoft\vscode-cpptools\ipch”目录下有很多缓存文件可以清理。 查询了一下&#xff1a;C/C 扩展常见问题解答 (visualstudio.com) 该件夹内包含缓存的预编译头文…

vscode markdown 使用技巧 -- 如何快速打出一个Tab 或多个空格

背景描述&#xff1a; 我在使用VSCode&#xff0c;这玩意很好用&#xff0c;但是&#xff0c;有一个缺点是&#xff0c;我想使用Tab来做一些对齐&#xff0c;但是我发现在VSCode中&#xff0c;无论是Tab还是多个空格&#xff0c;最终显示出来的都是一个空格 使用代码可以实现打…

基于ssm的宠物医院管理系统的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;Vue 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#xff1a;是 目录…

搞定蓝牙——第四章(GATT协议)

搞定蓝牙——第四章&#xff08;GATT协议&#xff09; 原理介绍层次结构server和client端Attribute ESP32代码 文章下面用的英文表示&#xff1a; server和client&#xff1a;服务端和客户端 char.&#xff1a;characteristic缩写&#xff0c;特征 Attribute:属性 ATT:Attribut…