数据结构-排序算法篇

前言

  在我们的生活中有很多东西都是有大小的,那么该如何去排序?假设有10个数字要你去排序,眼睛一扫就看出来了,那100、1000、10000····要怎么去排?下面就为大家介绍各种排序的算法。

内容

1.冒泡排序

2.选择排序

3.插入排序

4.希尔排序

5.快排

6.归并排序

7.计数排序

1.冒泡排序

   冒泡排序排序是一种交换排序,第一个数与第二个数进行比较(这里排序都默认是升序)如果第二个数小于第一个数,那就交换这两数位置然后第二个数再和第三个数依次进行比较,最后会将这个数组中最大数移动到数组最后的位置。

图解

代码
//冒泡排序
void BubbleSort(int* a, int n)
{for (int i = 0; i < n; i++){//j<n-i这样写是因为每比遍历一次数组就将最大的数放到了数组的最后面//下次排序就不用再比较了可以提高效率int flang = 1;//假设已经这个数组已经有序了for (int j = 0; j < n - i; j++){if (j + 1<n && a[j + 1] < a[j])//j + 1 < n是为防止越界{flang = 0;//进入到这里说明数组还没有完全有序Wsap(&a[j + 1], &a[j]);}}//如果flang==1那就说明这个数组已经有序就可以直接终止循环提高效率//防止出现 9 1 2 3 4 5 6 7 8 这种情况可以提升代码的效率if (flang == 1){break;}}
}

2.选择排序

图解

代码
// 选择排序
void SelectSort(int* a, int n)
{int min = 0;for (int j = 0; j < n; j++){min = j;for (int i = j; i < n; i++){if (a[i] < a[min]){min = i;}}Wsap(&a[j], &a[min]);}
}
//优化算法
void SelectSortpro(int* a, int n)
{int min = 0,max = 0;//用begin和end来控制数组的左右两边int begin = 0, end = n - 1;while (begin < end){for (int i = begin; i <= end; i++){if (a[i] < a[min]){min = i;}if (a[i] > a[max]){max = i;}}Wsap(&a[begin], &a[min]);if (a[min] > a[max]){max = min;}Wsap(&a[end], &a[max]);//每次遍历之后因为已经将此次遍历的最小和最大放到了两边所以需要缩小区间begin++;end--;}
}

3.插入排序

        首先要将数组分为已排序和未排序两个部分,一般需要从第二个元素开始因为第一个元素只有一个已经有序了。

图解

代码
// 插入排序
void InsertSort(int* a, int n)
{for (int i = 0; i < n-1; i++){int begin = 0, end = i;int key = a[end + 1];while (end >= begin){if (key < a[end]){a[end + 1] = a[end];end--;}//当a[end]>key时就停止循环这时end+1的位置是要插入key的位置else{break;}}//当数组的首元素位置是要插入key的时候end=-1所以end需要加一才是首元素的位置a[end + 1] = key;}
}

4.希尔排序

图解

代码
// 希尔排序
void ShellSort(int* a, int n)
{int gap = n;//当需要排序的内容过多时不再3组3组的分,需要数组长度不断除3来提升效率//除完加一是保证最后gap除3之后为零时gap= 1while (gap > 1){gap = gap/3+1;for (int i = 0; i < n - gap; i++)//i<n-gap 是保证数组不会越界{int end = i;int key = a[end + gap];while (end >= 0){if (key < a[end]){a[end + gap] = a[end];end -= gap;}else{break;}}a[end + gap] = key;}}
}

5.快排

  快排需要借助递归来实现快排的版本有很多图解中为大家一一叙述,快排的非递归需要借助栈来是实现这里就不过多的叙述了详细的思想见图解。

霍尔版本

   霍尔版本的快排,需要选择数组最左边的值做为key然后定义一个left和right分别指向最左边和最右边的元素然后right先走遍历数组找到比key小的数停止,left遍历找到比key大的停止然后left和right交换一直到left遇到right或者right遇到left停止,然后交换left或right和key的位置。由key分割数组的区间进行,递归操作。

图解

代码
//霍尔版本
int QuickSort1(int* a, int begin, int end)
{int key = a[begin], left = begin, right = end, key1 = begin;while (left < right){while (left < right && a[right] > key)//找比key小的数{right--;}while (left < right && a[left] <= key)//找比key大的数{left++;}Wsap(&a[left], &a[right]);}Wsap(&a[left], &a[key1]);return left;
}
//快排
void QuickSort(int* a, int begin, int end)
{if (begin >= end){return;}int key = QuickSort1(a, begin, end);QuickSort(a, begin, key - 1);QuickSort(a, key+1, end);
}

双指针法

  双指针法的也需要定义一个key指向数组最左边的值,再定义一个prev和cur,prev指向首元素的位置,cur的指向prev的下一个元素。 比较key和cur位置的值如果cur下于key那么就交换prev和cur位置的值如果cur大于key那么cur就加加,直到cur=right就结束。

代码
//双指针法
int QuickSort2(int* a, int left, int right)
{int prev = left, cur = left + 1, key = left;while (cur <= right){//++prev != cur 是为了防止prev和cur相等时交换可以提升效率if (a[cur] < a[key] && ++prev != cur){Wsap(&a[cur], &a[prev]);}else{cur++;}}Wsap(&a[key], &a[prev]);return prev;
}
void QuickSort(int* a, int begin, int end)
{if (begin >= end){return;}int key = QuickSort1(a, begin, end);QuickSort(a, begin, key - 1);QuickSort(a, key+1, end);
}

挖坑法

  首先定义key存储首元素,将首元素的位置看做一个坑定义变量ken,再定义一个begin,和end用来遍历数组,end先遍历找到比key小的元素就停止,然后让ken的位置等于end指向的元素再使end位置成为一个新的坑也就是使ken=end。然后begin开始遍历找比key大的数找到后停止再使ken的位置等于begin位置所指向的元素再使begin位置成为新的坑。直到begin和end相遇然后让begin和end指向的位置等于key。

代码
//挖坑法
int QuickSort3(int* a, int left, int right)
{int ken = left, key = a[left], begin = left, end = right;while (begin < end){while (a[end] >= key&& begin < end){end--;}a[ken] = a[end];ken = end;while (a[begin] <= key&& begin < end){begin++;}a[ken] = a[begin];ken = begin;}a[begin] = key;return begin;
}
//快排
void QuickSort(int* a, int begin, int end)
{if (begin >= end){return;}int key = QuickSort3(a, begin, end);QuickSort(a, begin, key - 1);QuickSort(a, key+1, end);
}

快排的优化

三数取中和小区间优化

代码
//三数取中
int GetMid(int left, int mid, int end)
{if (left > mid){if (end > left)//end>left>mid{return left;}else if (mid > end){return mid;}else{return end;}}else//mid>left{if (end > mid)//end>mid>left{return mid;}else if (left > end)//mid>left>end{return left;}else{return end;}}
}
//快排
void QuickSort(int* a, int begin, int end)
{if (begin >= end){return;}if (end - begin + 1 <= 10){InsertSort(a, end - begin + 1);}else{int key = QuickSort3(a, begin, end);QuickSort(a, begin, key - 1);QuickSort(a, key + 1, end);}
}

6.归并排序

递归版本

  归并的本质是分组,将数组分成两份一份是有序的另一份也是有序的,然后创建数组tmp从两份有序的数首元素开始遍历谁小谁就尾插到tmp数组中,直到两份数组都没有元素。将tmp数组中的内容拷贝到原数组中。

代码
//归并排序
void _MergeSort(int* a, int* tmp, int left, int right)
{	if (left == right){return;}int mid = (right + left) / 2;_MergeSort(a, tmp, left, mid);_MergeSort(a, tmp, mid+1, right);int begin1 = left, begin2 = mid+1, end1 = mid, end2 = right;int j = 0;while (begin1 <= end1 && begin2 <= end2){//谁小谁就尾插到tmp中if (a[begin1] <= a[begin2]){tmp[j++] = a[begin1++];}else{tmp[j++] = a[begin2++];}}//当出现6 7 8 9,2 3 4 5时6大于第二份中的所有数时//我们需要将第一份剩余是数组继续插入到tmp中while (begin1 <= end1){tmp[j++] = a[begin1++];}while (begin2 <= end2){tmp[j++] = a[begin2++];}//每次递归都要拷贝一次因为本质是对a中的数据排序但是现在我们是在tmp使其有序//所以每次排序完都要拷贝回去使a中也有序memcpy(a+left, tmp, (right - left + 1)*sizeof(int));
}
//归并排序
void MergeSort(int* a, int n)
{//创建数组tmpint* tmp = malloc(sizeof(int) * n+1);if (tmp == NULL){perror("tmp fail:");return;}_MergeSort(a, tmp, 0, n);
}

非递归版本 

        当递归的层度太深的话就会导致栈溢出的分险,所以我们需要尝试不借用递归实现归并排序。归并的本质是对数组进行分组比较,最开始的时候是每组有一个元素然后每相邻的两个组进行比较。1X1归并2X2归并4X4归并直到数组有序(当然也会出现不能均匀分割的情况,但是3X4依旧可以归并)。归并的难点在于怎么样去控制下标进行分组,首先对数组进行1X1的分组定义变量gap=1(gap组),进行遍历数组相邻的两组进行比较,小的就尾插到copy数组中,然后再将已经有序的部分拷贝会原数组中这是一次循环,在这个循坏外再加上一次循环用来控制每组元素的个数直到整个数组有序。

代码
//归并非递归
void MergeSortNOT(int* a, int n)
{//创建coap数组用于拷贝int* copy = (int*)malloc(sizeof(int)*(n+1));if (copy==NULL){perror("copy fail:");return;}int gap = 1;//组数while (gap < n){for (int i = 0; i < n; i += 2 * gap){//定义变量分割区间int begin1 = i, end1 = i + gap - 1, begin2 = i + gap, end2 = i + 2 * gap - 1;//printf("[%d %d] [%d %d]", begin1, end1, begin2, end2);//防止越界情况的发生if (end1 > n){break;}if (end2 > n){end2 = n - 1;}int j = 0;while (begin1 <= end1 && begin2 <= end2){//谁小谁就尾插到tmp中if (a[begin1] <= a[begin2]){copy[j++] = a[begin1++];}else{copy[j++] = a[begin2++];}}while (begin1 <= end1){copy[j++] = a[begin1++];}while (begin2 <= end2){copy[j++] = a[begin2++];}memcpy(a+i, copy, (end2-i+1) * sizeof(int));}gap*=2;printf("\n");}
}

7.计数排序

  计数排序是创建一个数组count用来记录a数组中元素的出现的个数,然后通过数组下标的自然有序使a数组中的元素出现在正确的位置上,使a有序。

代码
//计数有序
void CountSort(int* a, int n)
{//首先找出数组中的最大,最小值int max = a[0], min = a[0];for (int i = 0; i < n; i++){if (a[i] > max)max = a[i];if (a[i] < min)min = a[i];}//创建max-min+1个空间是为防止出现6 6 6 6 10的情况减少申请的内存空间int* count = calloc((max-min+1),sizeof(int));if(count==NULL){perror("count fail::");}for (int i = 0; i < n; i++){count[a[i] - min]++;}int b = 0;for (int j = 0; j < (max-min+1); j++){while (count[j]--){a[b++] = j + min;}}free(count);
}

总结

本篇章讲述了大部分的常用的排序,还有一个堆排将在二叉树中详细讲解。

希望大大多多指点。

记得三连哦!感谢!感谢!感谢!

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

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

相关文章

windows USB设备驱动开发-开发USB 设备端驱动

USB 设备是通过单个端口连接到计算机的外设&#xff0c;例如鼠标设备和键盘。 USB 客户端驱动程序是计算机上安装的软件&#xff0c;该软件与硬件通信以使设备正常运行。 如果设备属于 Microsoft 支持的设备类&#xff0c;Windows 会为该设备加载 Microsoft 提供的 USB 驱动程序…

简单分享下python封装

目录&#xff1a; 一、简介&#xff0c;什么是封装 二、封装的优点与好处 三、封装的示例 四、可封装的场景 一、简介&#xff0c;什么是封装 通俗理解&#xff1a;封装&#xff0c;简而言之&#xff0c;就是把数据&#xff08;变量&#xff09;和操作这些数据的方法&#xff0…

TongRDS2214手动部署版指引(by lqw+sy)

文章目录 前言准备工作单机版集群版哨兵版多个中心节点配置 前言 由于一些特殊原因&#xff08;例如服务器没有联网&#xff0c;没有办法直接更新和下载unzip指令&#xff0c;从而导致控制台版本安装节点之后&#xff0c;会报file not found的错误&#xff0c;或者使用不了rds…

(PC+WAP)高端大气的装修装潢公司网站模板

(PCWAP)高端大气的装修装潢公司网站模板PbootCMS内核开发的网站模板&#xff0c;该模板适用于装修公司网站、装潢公司网站等企业&#xff0c;当然其他行业也可以做&#xff0c;只需要把文字图片换成其他行业的即可&#xff1b;(PCWAP)&#xff0c;同一个后台&#xff0c;数据即…

Pandas实战秘籍:轻松驾驭重复值与异常值的处理艺术,让数据清洗更高效!

1.导包 import numpy as np import pandas as pd2.删除重复行 def make_df(indexs,columns):data [[str(j)str(i) for j in columns] for i in indexs]df pd.DataFrame(datadata,indexindexs,columnscolumns)return df使用 duplicated() 函数检测重复的行 返回元素为布尔类…

如何下载huggingface仓库里某一个文件

如何下载huggingface仓库里某一个文件&#xff1a; https://huggingface.co/PixArt-alpha/PixArt-Sigma/tree/main 直接用命令&#xff1a; wget https://huggingface.co/PixArt-alpha/PixArt-Sigma/resolve/main/PixArt-Sigma-XL-2-2K-MS.pth

信息学奥赛初赛天天练-42-CSP-J2020基础题-变量地址、编译器、逻辑运算、逻辑与运算、逻辑或运算、冒泡排序、递归应用

PDF文档公众号回复关键字:20240702 2020 CSP-J 选择题 单项选择题&#xff08;共15题&#xff0c;每题2分&#xff0c;共计30分&#xff1a;每题有且仅有一个正确选项&#xff09; 1.在内存储器中每个存储单元都被赋予一个唯一的序号&#xff0c;称为&#xff08; &#xff0…

VUE项目安全漏洞扫描和修复

npm audit 1、npm audit是npm 6 新增的一个命令,可以允许开发人员分析复杂的代码并查明特定的漏洞。 2、npm audit名称执行&#xff0c;需要包package.json和package-lock.json文件。它是通过分析 package-lock.json 文件&#xff0c;继而扫描我们的包分析是否包含漏洞的。 …

Polygon链的对接及使用

Polygon&#xff08;前身为Matic Network&#xff09;是一个基于以太坊的侧链&#xff0c;旨在解决以太坊网络拥堵和高昂 gas 费的问题。Polygon 使用侧链技术将交易从以太坊主网转移到自己的侧链上&#xff0c;从而提高交易速度和降低 gas 费。北京木奇移动技术有限公司&#…

Python语言接入关键词搜索商品api疑点解析

接入关键词搜索商品API通常需要以下步骤&#xff1a; 了解API文档&#xff1a;首先&#xff0c;你需要阅读API的文档&#xff0c;了解API的基本功能、请求方式&#xff08;GET、POST等&#xff09;、请求参数、返回数据格式等信息。 安装必要的库&#xff1a;根据API的要求&am…

使用Python绘制动态螺旋线:旋转动画效果

文章目录 引言准备工作前置条件 代码实现与解析导入必要的库初始化Pygame绘制螺旋线函数主循环 完整代码 引言 螺旋线是一个具有美学和数学魅力的图形。通过编程&#xff0c;我们可以轻松创建动态旋转的螺旋线动画。在这篇博客中&#xff0c;我们将使用Python和Pygame库来实现…

精准检测,守护安全:可燃气体报警器检测范围探讨

随着工业化进程的加快&#xff0c;易燃易爆气体的使用日益普遍&#xff0c;其安全隐患也愈发凸显。可燃气体报警器作为一种重要的安全监测设备&#xff0c;能够在气体泄漏时及时发出警报&#xff0c;预防火灾和爆炸事故的发生。 在这篇文章中&#xff0c;佰德将对可燃气体报警…

FPGA工程师有前途吗 ?FPGA崛起之路

全球 FPGA 市场规模犹如滚雪球般逐年扩大。 根据Gartner Group预测&#xff0c;2020-2026年全球FPGA市场规模从55.85亿美元增至96.9亿美元&#xff0c;年均复合增长率为9.6%。 众多国际知名科技企业&#xff0c;如赛灵思、Lattice等&#xff0c;纷纷加大在 FPGA 研发和应用方…

❤ Gitee平台的使用

Gitee平台的使用 文章目录 Gitee平台的使用一、Gitee的注册1、注册2、添加邮箱 二、仓库的创建 和 团队成员的添加1、单击右上角的 **&#xff0b;** 号 、创建仓库2、如下填写即可 三、仓库克隆到本地1、安装好git 和 小乌龟&#xff08;TortoiseGit&#xff09;2、打开仓库 复…

强化学习的数学原理:最优贝尔曼公式

大纲 贝尔曼最优公式是贝尔曼公式的一个特殊情况&#xff0c;但其也非常重要。 本节课很重要的两个概念和一个工具&#xff1a; 工具不用多说&#xff0c;就是贝尔曼最优公式&#xff0c;概念则是 optimal state value&#xff08;最优状态价值&#xff09; 和 optimal polic…

【博主推荐】HTML5实现简洁好看的个人简历网页模板源码

文章目录 1.设计来源1.1 主界面1.2 关于我界面1.3 工作经验界面1.4 学习教育界面1.5 个人技能界面1.6 专业特长界面1.7 朋友评价界面1.8 获奖情况界面1.9 联系我界面 2.效果和源码2.1 动态效果2.2 源代码 源码下载万套模板&#xff0c;程序开发&#xff0c;在线开发&#xff0c…

2024 年江西省研究生数学建模竞赛题目 A题交通信号灯管理---完整文章分享(仅供学习)

问题&#xff1a; 交通信号灯是指挥车辆通行的重要标志&#xff0c;由红灯、绿灯、黄灯组成。红灯停、绿灯行&#xff0c;而黄灯则起到警示作用。交通信号灯分为机动车信号灯、非机动车信号灯、人行横道信号 灯、方向指示灯等。一般情况下&#xff0c;十字路口有东西向和南北向…

【深度学习】图生图img3img论文原理,SD EDIT

https://arxiv.org/abs/2108.01073 摘要 引导图像合成技术使普通用户能够以最小的努力创建和编辑逼真的图像。关键挑战在于平衡对用户输入&#xff08;例如&#xff0c;手绘的彩色笔画&#xff09;的忠实度和合成图像的真实感。现有的基于GAN的方法试图通过使用条件GAN或GAN反…

webpack源码深入--- webpack的编译主流程

webpack5的编译主流程 根据watch选项调用compiler.watch或者是compiler.run()方法 try {const { compiler, watch, watchOptions } create();if (watch) {compiler.watch(watchOptions, callback);} else {compiler.run((err, stats) > {compiler.close(err2 > {callb…

【最新】2024年全球汽车零部件供应商百强榜,15家中企上榜!

6月23日&#xff0c;《美国汽车新闻》&#xff08;Automotive News&#xff09;重磅发布了2024年全球汽车零部件供应商百强榜。来自中国的动力电池企业宁德时代挤进了前四&#xff0c;中国企业一共上榜15家&#xff0c;较去年多了两家。国轩高科和三花零件为新进榜单的中企。 …