C++ 数据结构算法 学习笔记(32) -五大排序算法

C++ 数据结构算法 学习笔记(32) -五大排序算法

选择算法

如下若有多个女生的身高需要做排序:

在这里插入图片描述

常规思维:

  1. 第一步先找出所有候选美女中身高最高的,与最后一个数交换

在这里插入图片描述

  1. 第二步再找出除最后一位美女外其它美女中的最高者,与倒数第二个美女交换位置

在这里插入图片描述

  1. 再找出除最后两位美女外其它美女中的最高者,与倒数第三个美女交换位置,因为倒数 第三个本身已是最大的,所以实际无需交换.

在这里插入图片描述

  1. 重复以上步骤,直到最后只剩下一人,此时,所有的美女均已按照身高由矮到高的 顺序排列

在这里插入图片描述

代码实现:

#include<stdio.h>
#include<stdlib.h>
void swap(int* num1, int* num2)//交换两个变量的值
{int temp = *num1;*num1 = *num2;*num2 = temp;
}void SelectSort1(int arr[], int len) {for (int i = 0; i < len - 1; i++) {int max = 0;for (int j = 1; j < len - i; j++) { //查找未排序的元素if (arr[j] > arr[max]) { //找到目前最小值max = j;}}//printf("max:%dbeauties%d\n",max,len-i-1);if (max != (len - i - 1)) {swap(&arr[max], &arr[len - i - 1]);}}
}
void SelectSort2(int arr[], int len) {int i, j;for (i = 0; i < len - 1; i++){int min = i;for (j = i + 1; j < len; j++) { //查找未排序的元素if (arr[j] < arr[min]) { //找到目前最小值min = j; //记录最小值}}swap(&arr[min], &arr[i]); //交换}
}
int main(void) {int beauties[] = { 163,161,158,165,171,170,163,159,162 };int len = sizeof(beauties) / sizeof(beauties[0]);SelectSort2(beauties, len);for (int i = 0; i < len; i++) {printf("%d ", beauties[i]);}system("pause");
}

冒泡算法

当我们采用前面的选择排序时,我们仍然要将候选者遍历5遍,才能完成最终的排序,但其 实,本身这些美女出了第一个外,已经很有序了,我们只需要把第一个和第二个交换,然后又和 第三个交换,如此循环,直到和最后一个交换后,整个数组基本就有序了!

在这里插入图片描述

当然,并不是每次都这么幸运,像下面的情况就会更复杂一些,一趟并不能完全解决问题, 我们需要多趟才能解决问题.

在这里插入图片描述

经过上述五步后,得到的结果:

在这里插入图片描述

此时,我们只保障了最后一个数是最大的,并不能保障前面的数一定会有序,所以,我们继续按 照上面五步对剩下的5个数继续进行一次排序,数组就变得有序了. 以上过程就是冒泡排序:通过重复地遍历未排序的数列,一次比较两个元素,如果它们的顺 序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列 已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢得像泡泡一样“”到数 列的顶端,故而得名

代码实现:

#include <iostream>
#include <string>using namespace std;void swap(int* tmp1, int* tmp2)
{int tmp3 = *tmp1;*tmp1 = *tmp2;*tmp2 = tmp3;
}int main()
{int height2[] = { 156,162,161,172,167,169,155 };int height[] = { 155,158,161,163,172,174 };int size = sizeof(height) / sizeof(height[0]);for (int i = 0; i < size-1; i++){bool sorted = true;for (int j = 0; j < size-i-1; j++){if (height[j] > height[j+1]){	sorted = false;swap(&height[j], &height[j + 1]);}}if (sorted == true)	break;}for (int i = 0; i < size; i++){cout << height[i] << " ";}system("pause");return 0;
}

插入排序

在这里插入图片描述

  1. 首先,我们只考虑第一个元素,从第一个元素171开始,该元素可以认为已经被排序;

在这里插入图片描述

  1. 取下一个元素161并记录,并让161所在位置空出来,在已经排序的元素序列中从后向前扫 描;

    在这里插入图片描述

  2. 该元素(171)大于新元素,将该元素移到下一位置;

    在这里插入图片描述

  3. 171前已经没有最大的元素了,则将161插入到空出的位置

    在这里插入图片描述

  4. 取下一个元素163,并让163所在位置空出来,在已经排序的元素序列中从后向前扫描;

    在这里插入图片描述

  5. 该元素(171)大于新元素163,将该元素移到下一位置

    在这里插入图片描述

  6. 继续取171前的元素新元素比较,直到找到已排序的元素小于或者等于新元素的位置;新 元素大于161,则直接插入空位中

    在这里插入图片描述

  7. 重复步骤2~7,直到完成排序

    在这里插入图片描述

插入排序:它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描, 找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间 的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供 插入空间。

具体算法描述如下:

  1. 从第一个元素开始,该元素可以认为已经被排序;

  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描;

  3. 如果该元素(已排序)大于新元素,将该元素移到下一位置; 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;

  4. 将新元素插入到该位置; 重复步骤2~5

代码实现::

#include <iostream>
#include <string>using namespace std;void InsertSort(int* height, int size) 
{int current = 0;int preIndex = 0;for (int i = 1; i < size; i++){current = height[i];preIndex = i-1;while (preIndex >= 0 && height[preIndex] > current){height[preIndex + 1] = height[preIndex];preIndex--;}height[preIndex + 1] = current;}
}int main()
{int height[] = { 152,163,161,159,172,170,168,151 };int size = (sizeof(height) / sizeof(height[0]));InsertSort(height, size);cout << "The sorting result is" << endl;for (int i = 0; i < size; i++){cout << height[i] << " ";}system("pause");return 0;
}

希尔排序

插入排序虽好,但是某些特殊情况也有很多缺点,比如像下面这种情况

在这里插入图片描述

169前的元素基本不用插入操作就已经有序,元素1和2的排序几乎要移动数组前面的所有 元素!!!于是,有个老帅哥就提出了优化此问题的希尔排序!

希尔排序是希尔(Donald Shell)于1959年提出的一种排序算法。希尔排序也是一种插入排 序,它是简单插入排序经过改进之后的一个更高效的版本,也称为缩小增量排序。它与插入排序 的不同之处在于,它会优先比较距离较远的元素。

希尔排序是把记录按下表的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐 渐减少,每组包含的元素越来越多,当增量减至1时,所有元素被分成一组,实际上等同于执行一 次上面讲过的插入排序,算法便终止。

希尔排序的基本步骤:

选择增量:gap=length/2,缩小增量:gap=gap/2

增量序列:用序列表示增量选择,{n/2,(n/2)/2,…,1}

先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,具体算法描述:

选择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;

按增量序列个数k,对序列进行k趟排序;

每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m的子序列,分别对各子表进 行直接插入排序;

仅增量因子为1时,整个序列作为一个表来处理,表长度即为整个序列的长度。

在这里插入图片描述

#include <iostream>
#include <string>
using namespace std;void InsertSort(int arr[], int len)
{int gap = len / 2;for (; gap > 0; gap = gap / 2) {for (int i = gap; i < len; i++) {int current = arr[i];int j = 0;for (j = i - gap; j >= 0 && arr[j] > current; j -= gap) {arr[j + gap] = arr[j];}arr[j + gap] = current;}}
}int main()
{int height[] = { 152,163,161,159,172,170,168,151 };int size = (sizeof(height) / sizeof(height[0]));InsertSort(height, size);cout << "The sorting result is" << endl;for (int i = 0; i < size; i++){cout << height[i] << " ";}system("pause");return 0;
}

归并排序

当两个组数据已经有序,我们可以通过如下方式(以下简称归并大法)让两组数据快速有序

在这里插入图片描述

我们可以依次从两组中取最前面的那个最小元素依次有序放到新的数组中,然后再把新数组 中有序的数据拷贝到原数组中,快速完成排序
在这里插入图片描述

具体步骤:

对于下面这一组待排序的数组

在这里插入图片描述

先以中间为界,把其均分为A和B两个数组(如果是奇数个,允许两组数相差一个)

在这里插入图片描述

如果A和B两组数据能够有序,则我们可以通过上面的方式让数组快速排好序。 此时,A组有4个成员,B组有5个成员,但两个数组都无序,然后我们可以采用分治法继 续对A组和B组进行均分,以A组为例,又可以均分A1和A2两个组如下:

在这里插入图片描述

均分后,A1组和A2组仍然无序,继续利用分治法细分,以A1组为例,A1又可分成如下 两组

在这里插入图片描述

数组细分到一个元素后,这时候,我们就可以采用归并法借助一个临时数组将数组A1有序化! A2同理!

在这里插入图片描述

依次类推,将A1组和A2组归并成有序的A组,B组同理!

在这里插入图片描述

最后,将A和B组使用归并大法合并,就得到了完整的有序的结果!

在这里插入图片描述

代码实现:

#include <iostream>
#include <string>using namespace std;//void mergeAdd_demo(int arr[], int left, int mid, int right)
//{
//	int temp[64] = { 0 };
//	int i = left;
//	int j = mid;
//	int k = 0;
//
//	while (i < mid && j <= right)
//	{
//		if (arr[i] < arr[j])
//		{
//			temp[k++] = arr[i++];
//		}
//		else
//		{
//			temp[k++] = arr[j++];
//		}
//	}
//	while (i < mid)
//	{
//		temp[k++] = arr[i++];
//	}
//
//	while (j <= right)
//	{
//		temp[k++] = arr[j++];
//	}
//
//	memcpy(arr + left, temp, sizeof(int) * (right - left + 1));
//}void mergeAdd(int arr[], int left, int mid, int right, int* temp)
{//int temp[64] = { 0 };int i = left;int j = mid;int k = left;while (i < mid && j <= right){if (arr[i] < arr[j]){temp[k++] = arr[i++];}else{temp[k++] = arr[j++];}}while (i < mid){temp[k++] = arr[i++];}while (j <= right){temp[k++] = arr[j++];}memcpy(arr + left, temp + left, sizeof(int) * (right - left + 1));
}void mergeSort(int arr[], int left, int right, int* temp)
{int mid = 0;if (left < right){mid = left+(right-left)/2;mergeSort(arr, left, mid, temp);mergeSort(arr, mid + 1, right, temp);mergeAdd(arr, left, mid+1, right, temp);}
}int main()
{int height[] = { 10,11,12,13,2,4,5,8 };int len = sizeof(height) / sizeof(height[0]);int* temp = new int[len];//int mid = len / 2;mergeSort(height, 0, len - 1, temp);//mergeAdd(height, 0, mid, len - 1,temp);for (int i = 0; i < len; i++){cout << height[i] << " ";}system("pause");return 0;
}

快速排序

具体做法为:

  1. 每次选取第一个数为基准数;
  2. 然后使用“乾坤挪移大法”将大于和小于基准的元素分别放置于基准数两边;
  3. 继续分别对基准数两侧未排序的数据使用分治法进行细分处理,直至整个序列有序。

对于下面待排序的数组:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

代码实现:

#include <iostream>
#include <string>using namespace std;
int partition(int arr[], int low, int high)
{int i = low;int j = high;int base = arr[low];if (low < high){while (i < j){while (i < j && arr[j] >= base){j--;}if (i < j){arr[i++] = arr[j];}while (i < j && arr[i] < base){i++;}if (i < j){arr[j--] = arr[i];}}arr[i] = base;}return i;
}void QuickSort(int* arr, int low, int high)
{if (low < high){int index = partition(arr, low, high);QuickSort(arr, low, index - 1);QuickSort(arr, index + 1, high);}
}int main()
{int arr[] = { 163,161,158,165,171,170,163,159,162 };int len = sizeof(arr) / sizeof(arr[0]);//int index = partition(arr, 0, len - 1);QuickSort(arr, 0, len - 1);cout << "Executing the Quick Sort, result as" << endl;for (int i = 0; i < len; i++){cout << arr[i] << " ";}system("pause");return 0;
}

各大算法对比图

在这里插入图片描述

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

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

相关文章

k8s-pod详解

一、Pod基本概念&#xff1a; 1.pod介绍&#xff1a; Pod是kubernetes中最小的资源管理组件&#xff0c;Pod也是最小化运行容器化应用的资源对象。一个Pod代表着集群中运行的一个进程。kubernetes中其他大多数组件都是围绕着Pod来进行支撑和扩展Pod功能的&#xff0c;例如&am…

电赛经验分享——赛前准备

⏩ 大家好哇&#xff01;我是小光&#xff0c;想要成为系统架构师的嵌入式爱好者。 ⏩在之前的电赛中取得了省一的成绩&#xff0c;本文对电赛比赛前需要准备什么做一个经验分享。 ⏩感谢你的阅读&#xff0c;不对的地方欢迎指正。 加入小光嵌入式交流群&#xff08;qq群号&…

在线人才测评在企业招聘和大学生求职中的应用场景

每年的春招秋招&#xff0c;都是毕业生们忙着找工作的季节&#xff0c;相比社招来说&#xff0c;春招秋招是每个毕业生务必重视的机会&#xff0c;大厂名企毕竟名额有限&#xff0c;如果找到自己心仪的职业岗位&#xff0c;作为毕业生就必须提前准备&#xff0c;深入了解招聘的…

五管OTA输入极性快速判断

做CMFB还有负反馈的时候曾经在判断输入输出极性上吃了大亏&#xff0c;直接做实验波形正确就是输入正端&#xff0c;全差分就不用考虑这么多了 和弯折&#xff0c;形状类似7&#xff0c;相同方向输入正端&#xff0c;相反的就是输入负端&#xff0c;输出也是和输入负端一个方向…

【NLP】人机对话

概念 机器翻译就是用计算机把一种语言翻译成另外一种语言的技术 机器翻译的产生与发展 17 世纪&#xff0c;笛卡尔与莱布尼茨试图用统一的数字代码来编写词典 1930 机器脑 1933 苏联发明家特洛阳斯基用机械方法将一种语言翻译为另一种语言 1946 ENIAC 诞生 1949 机器翻译问题…

香蕉成熟度检测YOLOV8NANO

香蕉成熟度检测YOLOV8NANO&#xff0c;采用YOLOV8NANO训练&#xff0c;得到PT模型&#xff0c;然后转换成ONNX模型&#xff0c;让OEPNCV调用&#xff0c;从而摆脱PYTORCH依赖&#xff0c;支持C。python&#xff0c;安卓开发。能检测六种香蕉类型freshripe freshunripe overripe…

Vita-CLIP: Video and text adaptive CLIP via Multimodal Prompting

标题&#xff1a;Vita-CLIP: 通过多模态提示进行视频和文本自适应CLIP 源文链接&#xff1a;https://openaccess.thecvf.com/content/CVPR2023/papers/Wasim_Vita-CLIP_Video_and_Text_Adaptive_CLIP_via_Multimodal_Prompting_CVPR_2023_paper.pdfhttps://openaccess.thecvf.…

sw布尔减

可能最有效率还是草图边界线,然后用草图做分割

ue5 中ps使用记录贴

一、快捷键记录 放大图形 ctrlalt空格 放大图形 缩小视口 ctrl空格 ctrlD 取消选区 ctrlt缩小文字 w魔棒工具 选择魔棒的时候把容差打开的多一点 二、案例 移动文字 在相应的图层选择 移动文字 修改图片里的颜色 在通道里拷贝红色通道&#xff0c;复制红色通道粘贴给正常图…

记录Hbase出现HMaster一直初始化,日志打印hbase:meta,,1.1588230740 is NOT online问题的解决

具体错误 hbase:meta,,1.1588230740 is NOT online&#xff1b; state{1588230740 stateOPEN, ...... 使用 hbase 2.5.5 &#xff0c;hdfs和hbase分离两台服务器。 总过程 1. 问题发现 在使用HBase的程序发出无法进行插入到HBase操作日志后检查HBase状况。发现master节点和r…

大模型应用商业化落地关键:给企业带来真实的业务价值

2024 年被很多人称为大模型应用的元年&#xff0c;毫无疑问&#xff0c;大模型已经成为共识&#xff0c;下一步更急迫的问题也摆在了大家的面前——大模型到底能够用在哪&#xff1f;有哪些场景能落地&#xff1f;怎么做才能创造真正的价值&#xff1f; 在刚刚过去的 AICon 全…

【排序算法】快速排序(四个版本以及两种优化)含动图)

制作不易&#xff0c;三连支持一下吧&#xff01;&#xff01;&#xff01; 文章目录 前言一.快速排序Hoare版本实现二.快速排序挖坑法版本实现三.快速排序前后指针版本实现四.快速排序的非递归版本实现五.两种优化总结 前言 前两篇博客介绍了插入和选择排序&#xff0c;这篇博…

halcon配合yolov8导出onnx模型检测物体

1.工业上多数视觉开发都是用halcon开发的&#xff0c;halcon本身也有自己的深度学习网络&#xff0c;至于halcon如果不使用本身的深度学习&#xff0c;使用其他网络导出的onnx模型怎样配合使用&#xff1f;本文基于yolov8写一个列子。 2。创建输入数据的转换代码 #region 创建输…

Nginx高可用性架构:实现负载均衡与故障转移的探索

随着网络应用的不断发展和用户访问量的增长&#xff0c;如何确保系统的高可用性、实现负载均衡以及快速响应故障转移成为了每个运维和开发团队必须面对的挑战。Nginx作为一款高性能的HTTP和反向代理服务器&#xff0c;凭借其强大的功能和灵活的配置&#xff0c;成为了实现这些目…

题目:填空练习(指向指针的指针)

题目&#xff1a;填空练习&#xff08;指向指针的指针&#xff09; There is no nutrition in the blog content. After reading it, you will not only suffer from malnutrition, but also impotence. The blog content is all parallel goods. Those who are worried about …

【bugfix】/usr/local/bin/docker-compose:行1: html: 没有那个文件或目录

前言 在使用 docker-compose 管理容器化应用时&#xff0c;偶尔会遇到一些意想不到的错误&#xff0c;比如当尝试运行 docker-compose 命令时&#xff0c;终端非但没有展示预期的输出&#xff0c;反而出现类似网页错误的信息。这类问题通常与 docker-compose 的安装或配置有关…

首都师范大学聘请旅美经济学家向凌云为客座教授

2024年4月17日&#xff0c;首都师范大学客座教授聘任仪式在首都师范大学资源环境与旅游学院举行。首都师范大学资源环境与旅游学院院长吕拉昌主持了仪式&#xff0c;并为旅美经济学家向凌云教授颁发了聘书。 吕拉昌院长指出&#xff0c;要贯彻教育部产学研一体化战略&#xff0…

数据库工具类

public interface DbMapper {/*** 查询数据库类型*/String queryDbType(); }<select id"queryDbType" resultType"java.lang.String">select<choose><when test"_databaseId mysql">mysql</when><when test"_d…

虚拟机Centos扩展磁盘空间

虚拟机空间&#xff1a;现sda大小20G&#xff0c;因课程需要扩容 在虚拟机扩容中&#xff0c; 新增一块硬盘 和 直接在原有硬盘基础上扩容是一样的&#xff08;只不过在原有硬盘上扩容需要关机才可以执行&#xff09;&#xff1b; 但两者都最好先做数据备份或快照&#xff0c…

夏令营复习coding 算法第一天-状态:新奇

T1:bubble冒泡排序 &#xff08;1&#xff09;思路&#xff1a;两次循环&#xff0c;外层循环从后面开始-作为一个支点&#xff0c;内层循环每次将当前需要排序的最大的那个元素一步步移动到该支点&#xff0c;最终升序排列完成 &#xff08;2&#xff09;代码: #include &l…