【数据结构】十二、八种常用的排序算法讲解及代码分享

目录

一、插入排序

1)算法思想

2)代码

二、希尔排序

1)算法思想

2)代码

三、选择排序

1)算法思想

2)代码

四、堆排序

1)什么是最大堆

2)如何创建最大堆

3)算法思想

4)代码

五、冒泡排序

1)算法思想

2)代码

六、快速排序

1)算法思想

2)代码

七、归并排序

1)算法思想

2)代码

八、基数排序/桶排序(只对整数类型有效)

1)算法思想

2)代码


一、插入排序

1)算法思想

插入排序即将一个无序的元素集合中的元素一个个插入到子集合中合适的位置,直到原集合中的元素全部加入到子集合中。

2)代码

//插入排序
void Insert_Sort(DataType a[], int n)
{DataType temp;for (int i = 0; i < n - 1; i++)   //0 到 i 的数据已排序好{temp = a[i + 1];int j = i;while (j >= 0 && a[j] > temp) //如果是小于号则递增排序,如果是大于号则递减排序{a[j + 1] = a[j];j--;}a[j+1] = temp;}
}

二、希尔排序

1)算法思想

希尔排序算是插入排序的进阶版本,先把待排序的元素分为若干个小组,然后对每个小组进行插入排序

这里的“增量(span)”代表将相邻span的元素分为一组,span的取值一般取n/2

2)代码

//希尔排序
void Shell_Sort(DataType a[], int n)
{int span = n / 2;DataType temp;while (span > 0){for (int i = 0; i < span; i ++)  //将数组分为span个小组{//对各组进行插入排序for (int k = i; k < n - span; k += span){temp = a[k + span];int j = k;while (j >= 0 && a[j] > temp){a[j + span] = a[j];j -= span;}a[j + span] = temp;}}span /= 2;}
}

三、选择排序

1)算法思想

每次从待排序的集合中选择最小(或最大)的元素放到集合的最前面,元素集合不断缩小,当待排序集合为空时代表排序结束。

2)代码

//选择排序
void Select_Sort(DataType a[], int n)
{DataType temp;for (int i = 0; i < n; i++){DataType min = a[i];int k = i;for (int j = i; j < n; j++){if (a[j] < min){min = a[j];k = j;}}temp = a[i];a[i] = a[k];a[k] = temp;}
}

四、堆排序

1)什么是最大堆

1、完全二叉树结构;

2、双亲节点的值都比其孩子节点大。

2)如何创建最大堆

对于一个线性表,很容易可以将其转换为完全二叉树,因为线性表元素的下标是一一对应着完全二叉树的节点。我们先来记住两个重要的对应:

  1. (n-2)/ 2 :表示最后一个非叶子节点;

  2.    2 * i + 1 :表示第i个节点的左孩子;

将数组调整为大根堆的过程:

对应代码如下:

//其中n为数组a中的元素个数,h为要调整的元素的下标
static void CreatHeap(DataType a[], int n, int h)
{int flag = 0,i = h;DataType temp = a[i];int j = 2 * i + 1;   //先让j指向h左孩子节点的下标while (j < n && flag != 1){//寻找左右孩子节点中的较大者,j为其下标if (j < n - 1 && a[j] < a[j + 1]) j++;    //第一个判断条件为该节点是否有右孩子,第二个判断条件为右孩子是否比左孩子大,若是,则j代表右节点的下标if (temp > a[j]) flag = 1;else {a[i] = a[j];          //将j位置的值上移,并且j更新为其左孩子节点的值i = j;j = 2 * i + 1;     }}a[i] = temp;
}//创建大根堆
static void InitCreatHeap(DataType a[], int n)
{for (int i = (n - 2) / 2; i >= 0; i--)            //(n-2)/2表示左后一个非叶子节点的下标CreatHeap(a, n, i);
}

3)算法思想

通过第二部分的操作,我们已经成功地把数组转换为了大根堆,接下来只需要不断将根节点元素与数组末尾元素进行交换,再更新大根堆即可。

为什么不从最后面的叶子节点开始拿?因为我们无法保证最后一个元素一定是最小的!

例如:(a)将88和5进行交换,随后为保持为大根堆,5与76交换,再与50交换,得到(b)。

4)代码

void Heap_Sort(DataType a[], int n)
{DataType temp;InitCreatHeap(a, n);    //先初始化整个数组为大根堆for (int i = n - 1; i > 0; i--)    //不断将根节点元素放与数组末尾元素进行交换{temp = a[0];a[0] = a[i];a[i] = temp;CreatHeap(a, i, 0);}
}

五、冒泡排序

1)算法思想

冒泡排序是从第一个元素开始,将相邻的元素两个两个进行比较,每趟比较都将集合中最大(或最小)的元素放到了集合末尾

2)代码

//冒泡排序
void Bubble_Sort(DataType a[], int n)
{DataType temp;int flag = 1;            //判断是否提前排序完成for (int i = n; i > 0 && flag; i--){flag = 0;for (int j = 0; j < i-1; j++){if (a[j] > a[j + 1]){temp = a[j];a[j] = a[j + 1];a[j + 1] = temp;flag = 1;                //仍然有元素进行交换,排序未完成}}}
}

六、快速排序

1)算法思想

快速排序定义了一个数组的下界low和上界high,然后通过两端的指针不断与low处的元素进行比较,将比low处的元素小的元素放到左边,将所有比他大的元素放到右边,这样一来,该元素的左边的元素都比他小,右边的元素都比他大,然后递归对左边和右边的集合进行快速排序即可。

2)代码

//快速排序
static void QuickSort(DataType a[], int low,int high)
{int i = low, j = high;DataType temp = a[low];while (i < j) {while (i < j && temp <= a[j])j--;if (i < j) {a[i] = a[j];i++;}while (i < j && temp >= a[i])i++;if (i < j) {a[j] = a[i];j--;}}a[i] = temp;if(i>low) QuickSort(a, low, i - 1);if(j<high) QuickSort(a, j + 1, high);
}

诶!🧐这个排序有点不一样,前面的排序参数都是数组和元素个数,但是它居然有三个参数!逼死强迫症!为了使用时方便统一,我们封装一下:

//快速排序
void Quick_Sort(DataType a[], int n)
{QuickSort(a, 0, n - 1);   //注意上界和下界都是可取的
}

七、归并排序

1)算法思想

将具有n个元素的数组a看成n个长度为1的有序子数组,然后从第一个子数组开始,把相邻的两个子数组两两合并,然后再将合并后的数组两两合并,直到只剩下最后一个数组。

2)代码

//一次二路归并算法
static void Merge(DataType a[], int n, DataType swap[], int k)
{//k为有序子数组的长度,一次二路归并排序后的有序子数列存于swapint lower1 = 0;   //第一个有序子序列的下界int lower2, upper1, upper2,m = 0,i,j;while (lower1 + k <= n - 1) {lower2 = lower1 + k;       //第二个有序子数组的下界upper1 = lower2 - 1;       //第一个有序子数组的上界upper2 = (lower2 + k - 1 <= n - 1) ? lower2 + k - 1 : n - 1;//第二个有序子数组的上界//合并两个有序子数组for (i = lower1,j = lower2; i <= upper1 && j <= upper2; m++) {if (a[i] < a[j]) {swap[m] = a[i++];}else swap[m] = a[j++];}//如果子数组2已存完,则把数组1中剩余的元素存入swapwhile (i <= upper1) swap[m++] = a[i++];//如果子数组1已存完,则把数组2中剩余的元素存入swapwhile (j <= upper2) swap[m++] = a[j++];lower1 = upper2 + 1;}//如果原数组不能构成两组子数组,则直接存入swapfor (int i = lower1; i < n; i++, m++)swap[m] = a[i];
}//二路归并排序
void Merge_Sort(DataType a[], int n)
{DataType* swap = (DataType*)malloc(sizeof(DataType) * n);int k = 1;while (k < n){Merge(a, n, swap, k);for (int i = 0; i < n; i++)a[i] = swap[i];k *= 2;}free(swap);
}

八、基数排序/桶排序(只对整数类型有效)

1)算法思想

设待排序的元素是m位的d进制的数,不足m位的在高位补0,设置d个桶(实际上是队列),其编号为0、1、2…d-1。首先按照元素的低位的数组依次把各元素放入相应编号的队列中,然后从小到大的编号依次出队列,放回到原数组,这样就完成了一轮排序。接着按高一位的数值再次放入桶中,再出队列,直到进行m轮排列,数组中的元素就有序了。

2)代码

这里我们使用链式队列

//桶排序
//针对整数类型
void Radix_Sort(DataType a[], int n, int m, int d)  //m位的d进制数
{int k, power = 1;QueuePtr* tub = (QueuePtr*)malloc(sizeof(QueuePtr) * d);if (tub == NULL){printf("内存分配失败!\n");return;}for (int i = 0; i < d; i++) {LinkQueue_Init(&tub[i]);}//进行m次存放for (int i = 0; i < m; i++) {if (i == 0)power = 1;else power *= d;//将元素按关键字第k位的数值放入相应队列for (int j = 0; j < n; j++) {k = a[j] / power - (a[j] / (power * d)) * d;LinkQueue_Add(&tub[k], a[j]);}//顺序回收各队列中的元素至数值a中k = 0;for (int j = 0; j < n; j++) {while (!LinkQueue_Empty(tub[j])) {a[k++] = LinkQueue_Pop(&tub[j]);}}}
}

以上就是今天分享的全部内容,最后感谢你观看完我的文章,如果文章对你有帮助,可以点赞收藏评论,这是对作者最好的鼓励!不胜感激🥰

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

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

相关文章

C# Excel操作类EPPlus

摘要 EPPlus 是一个流行的用于操作 Excel 文件的开源库&#xff0c;适用于 C# 和 .NET 环境。它提供了丰富的功能&#xff0c;能够轻松地读取、写入和格式化 Excel 文件&#xff0c;使得在 C# 中进行 Excel 文件处理变得更加简单和高效。EPPlus 不需要安装 Microsoft Office 或…

ai写作文

天津市高考作文题 阅读下面的材料&#xff0c;根据要求写作。 在缤纷的世界中&#xff0c;无论是个人、群体还是国家&#xff0c;都会面对别人对我们的定义。我们要认真对待“被定义”&#xff0c;明辨是非&#xff0c;去芜存真&#xff0c;为自己的提升助力&#xff1b;也要勇…

知乎网站只让知乎用户看文章,普通人看不了

知乎默认不显示全部文章&#xff0c;需要点击展开阅读全文 然而点击后却要登录&#xff0c;这意味着普通人看不了博主写的文章&#xff0c;只有成为知乎用户才有权力查看文章。我想这不是知乎创作者希望的情况&#xff0c;他们写文章肯定是希望所有人都能看到。 这个网站篡改…

应用商店如何检测在架应用内容是否违规?

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…

线性代数|机器学习-P11方程Ax=b求解研究

文章目录 1. 变量数和约束条件数大小分类2. 最小二乘法和Gram-schmidt变换2.1 Gram-schmidt变换2.2 最小二乘法2.2.1 损失函数-Lasso 和regression2.2.2 损失函数-Lasso2.2.3 损失函数-regression2.2.4 Regression岭回归-矩阵验证2.2.5 Regression岭回归-导数验证 3. 迭代和随机…

人工智能的研究途径与方法

开篇 本文是学习《人工智能导论》这本书的笔记&#xff08;后续会持续更新&#xff09;。 正篇 心理模拟&#xff0c;符号推演 “心理模拟&#xff0c;符号推演”就是从人脑的宏观心理层面入手&#xff0c;以智能行为的心理模型为依据&#xff0c;将问题或知识表示成某种逻辑网…

【数据结构】队列——循环队列(详解)

目录 0 循环队列 1 特定条件下循环队列队/空队满判断条件 1.1 队列为空的条件 1.2 队列为满的条件 2 循环队列的实现 3 示例 4 注意事项 0 循环队列 循环队列&#xff08;Circular Queue&#xff09;是队列的一种实现方式&#xff0c;它通过将队列存储空间的最后一…

两个jsonl文件a和b,如何读取a文件中desc对应的值和type对应的值,然后在b文件中找到desc对应值相同的数据并把type的值写入?

两个jsonl文件a和b&#xff0c;如何读取a文件中desc对应的值和type对应的值&#xff0c;然后在b文件中找到desc对应值相同的数据并把type的值写入&#xff1f; import json# 读取a.jsonl文件中的数据 def read_jsonl(file_path):with open(file_path, r, encodingutf-8) as f:…

MySQL之多表查询—行子查询

一、引言 上篇博客学习了列子查询。 接下来学习子查询中的第三种——行子查询。 行子查询 1、概念 子查询返回的结果是一行&#xff08;当然可以是多列)&#xff0c;这种子查询称为行子查询。 2、常用的操作符 、 <> (不等于) 、IN 、NOT IN 接下来通过一个需求去演示和…

locale本地化库学习

std::locale 类型的对象&#xff08;本地环境对象&#xff09;是不可变刻面的一个不可变索引集。C 输入/输出库的每个流对象都与一个 std::locale 对象关联&#xff0c;并用它的各刻面来分析及格式化所有数据。另外&#xff0c;每个 std::basic_regex 对象也都与一个本地环境对…

Linux下软件安装

提示&#xff1a;制作不易&#xff0c;可以点个关注和收藏哦。 前言 介绍 Ubuntu 下软件安装的几种方式&#xff0c;及 apt&#xff0c;dpkg 工具的使用。 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考. 一、先体验一下 比如我们想安装一个软件&…

Diffusers代码学习: 多个Adapter

T2I Adapter也是可组合的&#xff0c;允许您使用多个适配器对图像施加多个控制条件。例如&#xff0c;可以使用姿势贴图提供结构控制&#xff0c;使用深度贴图进行深度控制。这是由[MultiAdapter]类启用的。 让我们用姿势和深度适配器来调节文本到图像的模型。创建深度和姿势图…

简单的项目部署脚本(转载)

简单的项目部署脚本 1. 环境准备1.1 java1.2 maven1.3 git 2 以项目springboot-demo为例,创建项目路径3. 基于docker启动的部署脚本4. 部署日志记录4.1 将部署开始和结束的日志追加到部署日志中4.2 部署结果通知 原文链接 https://mp.weixin.qq.com/s/jjW2aIi_KUusQdc9uLnUGg …

IT闲谈-Kylin入门教程

目录 一、引言二、Kylin简介三、环境准备四、安装与配置五、数据导入与建模六、查询与分析七、总结 一、引言 Apache Kylin是一个开源的分布式分析引擎&#xff0c;旨在提供Hadoop/Spark之上的SQL接口及多维分析&#xff08;OLAP&#xff09;能力以支持超大规模数据。Kylin通过…

【设计模式】结构型设计模式之 享元模式

文章目录 介绍关键概念 应用举例象棋游戏共享棋子对象文本编辑器中文字格式设计成享元模式 享元模式在 Java 中的应用享元模式在包装类缓存中的应用享元模式在 String 中的应用 对比享元模式和单例模式的区别享元模式与缓存的区别 总结优点缺点 介绍 享元模式&#xff0c;”享…

简单用java集合模拟斗地主发牌操作

简易斗地主发牌&#xff08;熟悉java集合的使用&#xff09; 1、需求 按照斗地主规则&#xff0c;完成洗牌发牌的动作。 具体要求如下&#xff1a; 1、准备牌&#xff1a;组装54张扑克牌 2、洗牌&#xff1a;54张牌顺序打乱 3、发牌&#xff1a;三个玩家参与游戏&#xf…

TinyVision V851s 使用 OpenCV + NPU 实现 Mobilenet v2 目标分类识别

用39块钱的V851se视觉开发板做了个小相机。 可以进行物品识别、自动追焦&#xff01; 这个超低成本的小相机是在V851se上移植使用全志在线开源版本的Tina Linux与OpenCV框架开启摄像头拍照捕获视频&#xff0c;并结合NPU实现Mobilenet v2目标分类识别以及运动追踪等功能......并…

以无厚,入有间,做一件事为什么靠努力不行,不能长期维持

庖丁解牛&#xff0c;并不是在说人和技巧&#xff0c;而是在说解牛不在于刀的锋利&#xff0c;而是怎样才能做到让刀不产生损耗&#xff0c;就是熟悉牛肉纹路&#xff0c;按照纹路和肉骨间隙进行操刀。这就是尊重自然规律&#xff0c;对于人也是一样的&#xff0c;如果所有事情…

C++输入输出与IO流

C 输入输出与I/O流 文章目录 C 输入输出与I/O流IO类型与基础特性概念与特性IO状态输出缓冲区 文件输入输出文件模式 string流IO处理中常用的函数及操作符综合练习与demo一、 创建文件并写入二、控制台输入数据并拆分存储三、读写电话簿 IO类型与基础特性 C11标准提供了几种IO处…

el-date-picker设置结束时间为23:59:59

type datetime <el-date-pickerstyle"width: 100%"v-model"currentEditConfigObj.expirationDate"placeholder"请选择结束时间"type"datetime"default-time[23:59:59]value-format"yyyy-MM-dd HH:mm:ss"format"yy…