排序(一)插入排序,希尔排序,选择排序,堆排序,冒泡排序

目录

一.排序

1.插入排序

2.希尔排序

3.选择排序

4.堆排序

5.冒泡排序

二.整体代码

1.Sort.h

2.Sort.c

3.test.c


一.排序

1.插入排序

插入排序基本思想:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为 止,得到一个新的有序序列

实现过程单趟排序:将插入值与前一个数进行比较,如果大就直接插入到后面,如果小,将前一个数后移,继续与之前的比较,小的话插入空的位置,否则继续向前比较

        我们可以将每一个排序分为单趟和整体排序,了解单趟排序,对于整体排序,我们可以将它看作将数据一个一个的向里面插入

void InsertSort(int* a, int n)
{assert(a);for (int i = 0; i < n - 1; ++i){//单趟排序,[0,end]有序,将end + 1向其中插入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;}
}

插入排序特性总结:

1.时间复杂度:O(N^2),顺序时最好,逆序时最坏

2.空间复杂度:O(1)

3.稳定性:稳定

4.当排序的数组越接近有序,算法的时间效率越高

2.希尔排序

我们将希尔排序分为预排序(使数组接近有序),然后直接插入排序

预排序:把间距为gap的值分为一组,进行插入排序

以gap为3为例的图

        当gap的值越大时,前面大的值可以更快的到后面,后面小的值可以更快的到前面,但是gap越大,数组内数据越不接近有序,而当gap为1的,就相当于插入排序

// 希尔排序
void ShellSort(int* a, int n)
{//gap>1相当于预排序,让数组接近有序int gap = n;while (gap > 1){gap = gap / 3 + 1;//+1保证了gap最后一次一定为1//gap==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;}}
}

希尔排序特性总结:

1.希尔排序是对插入排序的优化

2.当gap>1时为预排序,是为了让数组更接近有序,gap==1时数组已经基本有序,插入时就会较快.对于整个过程可以起到优化

3.稳定性:不稳定

4.gap的时间复杂度不好计算,因为gap的值不同

        在下图中我们可以看到对于一组数据插入排序和希尔排序的处理时间

我们可以看到希尔排序的处理速度相比于插入排序提升很大

3.选择排序

        选择排序:我们在begin和end的区间内寻找到最小值和最大值的下标,将最小值和最大值找到分别置于首和尾后,++begin,--end,缩小区间,继续寻找,直到搜索完整个区间

选择排序特性总结:

1.直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用

2.时间复杂度:O(N^2)

3.空间复杂度:O(1)

4.稳定性:不稳定

我们可以看到选择排序的处理效率与直接插入排序差不多

4.堆排序

        堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据。需要注意的是排升序要建大堆,排降序建小堆

堆排序在前面已经讲解过,在此不多解释

//向下调整
//小堆向下调整前提:左右子树都为小堆
//大堆向下调整前提:左右子树都为大堆
void AdjustDown(int* a, int n, int root)
{int parent = root;//将根节点位置给父节点int child = 2 * parent + 1;//子节点下标为2*parent+1while (child < n)//保证下标不越界{//找出左右孩子小的那个if (child + 1 < n && a[child + 1] > a[child]){++child;}//若孩子的值大于父亲则交换,并将孩子下标给父亲,重新计算孩子下标if (a[child] > a[parent]){Swap(&a[child], &a[parent]);parent = child;child = 2 * parent + 1;}//如果孩子大,则说明为小堆,不需要向下调整else{break;}}
}//堆排序
//1.升序建大堆
//2.降序建小堆
void HeapSort(int* a, int n)
{//建堆//假设树有N个节点,树高度:logN.时间复杂度:O(N)for (int i = (n - 1 - 1) / 2; i >= 0; --i){AdjustDown(a, n, i);//向下调整}int end = n - 1;//最后一个叶的下标while (end > 0){Swap(&a[0], &a[end]);AdjustDown(a, end, 0);--end;}
}

堆排序特性总结:

1. 堆排序使用堆来选数,效率就高了很多

2. 时间复杂度:O(N*logN)

3. 空间复杂度:O(1)

4. 稳定性:不稳定

5.冒泡排序

        冒泡排序:将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动,前后比较,大的就交换

// 冒泡排序
void BubbleSort(int* a, int n)
{assert(a);int end = n;while (end > 0){int exchange = 0;for (int i = 1; i < end; ++i){if (a[i - 1] > a[i]){Swap(&a[i - 1], &a[i]);exchange = 1;}}//如果一趟冒泡中没有发生交换,则说明已经有序,不需要冒泡if (exchange == 0){break;}}
}

冒泡排序特性总结:

1. 冒泡排序是一种非常容易理解的排序

2. 时间复杂度:O(N^2)

3. 空间复杂度:O(1)

4. 稳定性:稳定

二.整体代码

1.Sort.h

#pragma once
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <time.h>void PrintArray(int* a, int n);
void Swap(int* p1, int* p2);
void AdjustDown(int* a, int n, int root);
// 插入排序
void InsertSort(int* a, int n);// 希尔排序
void ShellSort(int* a, int n);// 选择排序
void SelectSort(int* a, int n);// 堆排序
void AdjustDown(int* a, int n, int root);
void HeapSort(int* a, int n);// 冒泡排序
void BubbleSort(int* a, int n);

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(1)
void InsertSort(int* a, int n)
{assert(a);for (int i = 0; i < n - 1; ++i){//单趟排序,[0,end]有序,将end + 1向其中插入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;}
}// 希尔排序
void ShellSort(int* a, int n)
{//gap>1相当于预排序,让数组接近有序int gap = n;while (gap > 1){gap = gap / 3 + 1;//+1保证了gap最后一次一定为1//gap==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;}}
}void Swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}// 选择排序
void SelectSort(int* a, int n)
{assert(a);int begin = 0, end = n - 1;while (begin < end){//在[bagin,end]之间找出最小数和最大数的下标int mini, maxi;mini = maxi = begin;for (int i = begin + 1; i <= end; ++i){if (a[i] > a[maxi]){maxi = i;}if (a[i] < a[mini]){mini = i;}}Swap(&a[begin], &a[mini]);//如果maxi和begin位置重叠,maxi需要修正if (begin == maxi){maxi = mini;}Swap(&a[end], &a[maxi]);++begin;--end;}
}//向下调整
//小堆向下调整前提:左右子树都为小堆
//大堆向下调整前提:左右子树都为大堆
void AdjustDown(int* a, int n, int root)
{int parent = root;//将根节点位置给父节点int child = 2 * parent + 1;//子节点下标为2*parent+1while (child < n)//保证下标不越界{//找出左右孩子小的那个if (child + 1 < n && a[child + 1] > a[child]){++child;}//若孩子的值大于父亲则交换,并将孩子下标给父亲,重新计算孩子下标if (a[child] > a[parent]){Swap(&a[child], &a[parent]);parent = child;child = 2 * parent + 1;}//如果孩子大,则说明为小堆,不需要向下调整else{break;}}
}//堆排序
//1.升序建大堆
//2.降序建小堆
void HeapSort(int* a, int n)
{//建堆//假设树有N个节点,树高度:logN.时间复杂度:O(N)for (int i = (n - 1 - 1) / 2; i >= 0; --i){AdjustDown(a, n, i);//向下调整}int end = n - 1;//最后一个叶的下标while (end > 0){Swap(&a[0], &a[end]);AdjustDown(a, end, 0);--end;}
}// 冒泡排序
void BubbleSort(int* a, int n)
{assert(a);int end = n;while (end > 0){int exchange = 0;for (int i = 1; i < end; ++i){if (a[i - 1] > a[i]){Swap(&a[i - 1], &a[i]);exchange = 1;}}//如果一趟冒泡中没有发生交换,则说明已经有序,不需要冒泡if (exchange == 0){break;}}
}

3.test.c

#include "Sort.h"// 测试排序的性能对比
void TestOP()
{srand(time(0));const int N = 10000;int* a1 = (int*)malloc(sizeof(int) * N);int* a2 = (int*)malloc(sizeof(int) * N);int* a3 = (int*)malloc(sizeof(int) * N);int* a4 = (int*)malloc(sizeof(int) * N);int* a5 = (int*)malloc(sizeof(int) * N);for (int i = 0; i < N; ++i){a1[i] = rand();a2[i] = a1[i];a3[i] = a1[i];a4[i] = a1[i];a5[i] = a1[i];}int begin1 = clock();InsertSort(a1, N);int end1 = clock();int begin2 = clock();ShellSort(a2, N);int end2 = clock();int begin3 = clock();SelectSort(a3, N);int end3 = clock();int begin4 = clock();HeapSort(a4, N);int end4 = clock();int begin5 = clock();BubbleSort(a5,  N);int end5 = clock();printf("InsertSort:%d\n", end1 - begin1);printf("ShellSort:%d\n", end2 - begin2);printf("SelectSort:%d\n", end3 - begin3);printf("HeapSort:%d\n", end4 - begin4);printf("BubbleSort:%d\n", end5 - begin5);free(a1);free(a2);free(a3);free(a4);free(a5);
}void TestInsertSort()
{int a[] = { 3,2,4,6,7,9,11,1,0 };PrintArray(a, sizeof(a) / sizeof(int));InsertSort(a, sizeof(a) / sizeof(int));PrintArray(a, sizeof(a) / sizeof(int));
}void TestShellSort()
{int a[] = { 9,8,7,6,5,4,3,2,1};PrintArray(a, sizeof(a) / sizeof(int));ShellSort(a, sizeof(a) / sizeof(int));PrintArray(a, sizeof(a) / sizeof(int));
}void TestSelectSort()
{int a[] = {5,4,7,6,4,2,9,7,8 };PrintArray(a, sizeof(a) / sizeof(int));SelectSort (a, sizeof(a) / sizeof(int));PrintArray(a, sizeof(a) / sizeof(int));
}void TestHeapSort()
{int a[] = { 1,8,4,7,6,3,9,12,6 };PrintArray(a, sizeof(a) / sizeof(int));HeapSort(a, sizeof(a) / sizeof(int));PrintArray(a, sizeof(a) / sizeof(int));
}void TestBubbleSort()
{int a[] = { 7,8,1,14,6,10,2,12,9 };PrintArray(a, sizeof(a) / sizeof(int));BubbleSort(a, sizeof(a) / sizeof(int));PrintArray(a, sizeof(a) / sizeof(int));
}int main()
{TestInsertSort();TestShellSort();TestSelectSort();TestHeapSort();TestBubbleSort();TestOP();
}

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

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

相关文章

ubuntu20.04上使用 Verdaccio 搭建 npm 私有仓库

安装nvm 首先安装必要的工具&#xff1a; apt update apt install curl下载并执行nvm安装脚本&#xff1a; curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash添加环境变量&#xff08;如果安装脚本没有自动添加&#xff09;。编辑 ~/.bash…

mysql建表

作业要求&#xff1a; 根据以下需求完成图书管理系统数据库及表设计&#xff0c;并建库建表&#xff0c;并截图创建表的详细信息(desc 表名),不用添加数据 1. 用户表: 字段: 姓名&#xff0c;用户名&#xff0c;密码&#xff0c;电话&#xff0c;住址&#xff0c;专业及年级…

命名空间std, using namespace std

命名空间std&#xff0c;using namespace std 在标准C以前&#xff0c;都是用#include<iostream.h>这样的写法的&#xff0c;因为要包含进来的头文件名就是iostream.h。标准C引入了名字空间的概念&#xff0c;并把iostream等标准库中的东东封装到了std名字空间中&#x…

系统设计-通用用户权限管理系统

通用用户权限管理系统 一、系统安全二、登录授权三、系统内部安全1. 相关实体1.1 实体关系(ER)2. 菜单权限3. 接口权限3.1 权限获取3.2 接口调用鉴权4. 数据权限四、其他一个没有权限控制的系统,是非常不安全的。 在日常业务运营的系统中台,基本都会存在用户的菜单权限控制,…

【华为路由】OSPF多区域配置

网络拓扑 设备接口地址 设备 端口 IP地址 RTA Loopback 0 1.1.1.1/32 G0/0/0 10.1.1.1/24 RTB Loopback 0 2.2.2.2/32 G0/0/0 10.1.1.2/24 G0/0/1 10.1.2.1/24 RTC Loopback 0 3.3.3.3/32 G0/0/0 10.1.2.2/24 G0/0/1 10.1.3.1/24 RTD Loopback 0 4.4.4…

与ai聊我的代码架构

以包目录结构模块&#xff0c;以*.py脚本收纳模块。 (笔记模板由python脚本于2024年10月25日 18:39:10创建&#xff0c;本篇笔记适合编程基础的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www.python.org/ Free&#xff1a;大咖免费“圣经”教程《…

在线教育(培训+考试)/企业培训-企业培训平台-企业培训平台系统-企业内部培训系统-在线教育-Java语言开发

介绍 企业培训平台支持企业培训考试全流程&#xff0c;在线学习、在线考试&#xff0c;成熟的企业培训考试解决方案&#xff0c;充分满足企业培训需求。 独立部署&#xff0c;仅内部员工登录使用&#xff0c;稳定、安全、高效&#xff0c;满足企业、政府、教育行业的各种在线学…

STM32-Modbus协议(一文通)

Modbus协议原理 RT-Thread官网开源modbus RT-Thread官方提供 FreeModbus开源。 野火有移植的例程。 QT经常用 libModbus库。 Modbus是什么&#xff1f; Modbus协议&#xff0c;从字面理解它包括Mod和Bus两部分&#xff0c;首先它是一种bus&#xff0c;即总线协议&#xff0c;和…

Maya---骨骼绑定

调节骨骼大小 回车键确认骨骼 FK子集跟父集走 IK子集不跟父集走 前视图中按shift键添加骨骼 清零、删除历史记录&#xff0c;创建新的物体

多元线性回归【正规方程/sklearn】

多元线性回归【正规方程/sklearn】 1. 基本概念1.1 线性回归1.2 一元简单线性回归1.3 最优解1.4 多元线性回归 2. 正规方程求最优解2.1 线性回归的损失函数&#xff08;最小二乘法&#xff09;2.2 推导正规方程2.3 正规方程练习2.4 使用sklearn计算多元线性方程2.5 凸函数 3. 线…

哪款宠物空气净化器噪音低?希喂、美的、安德迈测评分享

今年双11&#xff0c;宠物空气净化器到底应该如何选&#xff1f;在所有的家电品类里&#xff0c;宠物空气净化器算是比较特殊的那个&#xff0c;产品迭代太快&#xff0c;我们把今年双11在售的各大主流品牌的宠物空气净化器统一汇总整理&#xff0c;发现基本一多半都是24年下半…

【Unity 安装教程】

Unity 中国官网地址链接 Unity - 实时内容开发平台 | 3D、2D、VR & AR可视化https://unity.cn/首先我们想要安装Unity之前&#xff0c;需要安装Unity Hub&#xff1a; Unity Hub 是 Unity Technologies 开发的一个集成软件&#xff0c;它为使用 Unity 引擎的开发者提供了一…

使用Angular构建动态Web应用

&#x1f496; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4bb; Gitee主页&#xff1a;瑕疵的gitee主页 &#x1f680; 文章专栏&#xff1a;《热点资讯》 使用Angular构建动态Web应用 1 引言 2 Angular简介 3 安装Angular CLI 4 创建Angular项目 5 设计应用结构 6 创建组件…

Nature Communications|一种3D打印和激光诱导协同策略用于定制功能化器件(3D打印/激光直写/柔性电子/人机交互/柔性电路)

美国密苏里大学机械与航天工程系Jian Lin团队,在《Nature Communications》上发布了一篇题为“Programmed multimaterial assembly by synergized 3D printing and freeform laser induction”的论文。论文内容如下: 一、 摘要 在自然界中,结构和功能材料经常形成程序化的三…

《面向对象系统分析与设计》三级项目

文章目录 一、项目总体要求<设计模式应用>第一次文档要求第二次文档要求 二、示例第一次文档 - 设计原则应用1、题目描述2、设计:(1&#xff09;优化理由陈述(2&#xff09;类图(3)实现代码 第二次文档 - 设计模式应用1、题目描述2、设计:(1) 优化理由陈述(2&#xff09;…

【虚幻引擎UE】UE5 音频共振特效制作

UE5 音频共振特效制作 一、基础准备1.插件准备2.音源准备 二、创建共感NRT解析器和设置1.解析器选择依据2. 创建解析器3. 创建解析器设置&#xff08;和2匹配&#xff09;4.共感NRT解析器设置参数调整5.为共感NRT解析器关联要解析的音频和相应设置 三、蓝图控制1.创建Actor及静…

短剧AI突围战,百度跑偏了

“ 百度短剧的Agent对话功能并不属于颠覆性创新&#xff0c;只是新插件&#xff0c;对短剧行业市场格局影响不大&#xff0c;最多只能算用户痒点。 ” 转载&#xff1a;科技新知 原创 作者丨晓伊 编辑丨蕨影 你是否有过这样的体验&#xff1f; 刷短剧时&#xff0c;因剧情曲…

解决运行jar错误: 缺少 JavaFX 运行时组件, 需要使用该组件来运行此应用程序

报错 众所周知jdk8以上都没有Javafx java -jar target/myyscan-1.0-SNAPSHOT.jar 错误: 缺少 JavaFX 运行时组件, 需要使用该组件来运行此应用程序解决 https://gluonhq.com/products/javafx/ 去下载/javafx/到本地&#xff0c;选择自己的型号 然后记得指定路径 java --m…

TPLCM柔性屏自动化贴合应用

在当前的显示屏制造领域&#xff0c;TP&LCM贴合技术是推动产品升级和满足市场需求的关键环节。随着技术的不断进步&#xff0c;全贴合技术因其卓越的显示效果和用户体验&#xff0c;逐渐成为中高端产品的标配。然而&#xff0c;这一技术的高精度要求和复杂工艺也带来了诸多…

【C++ 算法进阶】算法提升七

目录 正数数组中那两个数&结果最大 &#xff08;贪心&#xff09;题目题目分析代码详解 最小相机覆盖问题 &#xff08;二叉树递归套路&#xff09;题目题目分析代码详解 拼接字符串 &#xff08;动态规划 前缀树&#xff09;题目题目分析代码详解 正数数组中那两个数&…