C++之五种排序方法总结

2023-10-27

 模板函数sort( )

sort是一个模板函数:sort( ),括号里可以接受两个或三个参数。这里先说一下两个参数的,因为三个参数的还没研究好,哈哈。

使用sort( )时需要添加头文件<algorithm>,这个英文单词的意思是“ 运算法则”。

接受两个参数时默认的排序方式是升序,添加第三个参数是为了实现降序。第一个参数是所要排序的数列的首地址,而第二个参数是该数列的最后一个数的地址加一。比如要对数组a[7]={5,7,9,10,8,2,3}排序,则是sort(a,a+7)。

#include<iostream>
#include<algorithm>
using namespace std;
int main() {
	int a[10]= {9,6,3,8,5,2,7,4,1,0};
	for(int i=0; i<10; i++)
		cout<<a[i]<<" ";
	cout<<endl;
	sort(a,a+10);                      #注意这是a+10
	for(int i=0; i<10; i++)
		cout<<a[i]<<" ";
	return 0;
}
运行结果:
9 6 3 8 5 2 7 4 1 0
0 1 2 3 4 5 6 7 8 9

桶排序方法

这个桶排序以前真没听说过。。。。看图:(其实是看表格了)

0 0 0 0 0 0 0 0 0 0 ...

a[0]      a[1]     a[2]    a[3]    a[4]    a[5]    a[6]   a[7]     a[8]    a[9]   a[...]  

这是一个初始化为零的数列,如果想要利用它来进行排序,例如这样一组数:6,3,9,6,8,7,5,4。

首先按照下标进行赋值,即:

0 0 0 1 1 1 2 1 1 1 ...

a[0]      a[1]    a[2]   a[3]    a[4]    a[5]    a[6]   a[7]     a[8]    a[9]     a[...]  

实际上已经按照下标的顺序排好了,只需按照里面的值输出就ok了。

#include<iostream>
#include<algorithm>
using namespace std;
int main() {
	int x,n;
	cin>>n;
	int a[100]= {0};
	for (int i=0; i<n; i++) {
		cin>>x;
		a[x]++;
	}
	for(int i=0; i<100; i++) {
		for(int m=1;m<=a[i];m++){
			cout<<i<<" ";}
		
	}
}

其实桶排序并没有在数组内部将这些数按照升序的方式排列,只是借助了下标将它们输出了。

冒泡排序

这种排序方法上课时老师讲过。主要的原理就是冒泡,哈哈哈。冒泡可以实现升序和降序的排列,例如一列数:2 3 6 8 10 5 1   七个数

升序排列的话 ,第一次循环:相邻的两个数进行比较,大的数则放在后面,这样第一次循环比较了六次:2 3  6 8 5  1 10。

可以看出第一次循环最大的值10浮出了水面。所以,可以推想出要想完成排序,最多要进行n-1次循环才行。并且每次循环所比较的次数在逐渐减小,因为一部分值已经按照顺序排好了位置。

#include<iostream>
using namespace std;
int main() {
	int n,exchange;
	cout<<"要排几个数:";cin>>n;
	int a[100];
	for (int i=0; i<n; i++) {
		cin>>a[i];	}
	for(int i=1; i<=n-1; i++)                 #主要算法
	{
		for(int j=1;j<=n-i;j++)
		{
			if(a[j-1]>a[j])
			{exchange=a[j-1];
		        a[j-1]=a[j];
		        a[j]=exchange;
			}
		}
	}
	for(int i=0;i<n;i++)
	{
		cout<<a[i]<<" ";
	}
	
}

选择排序 

还是这2 3 6 8 10 5 1七个数,按照升序的方法排,这次不再是冒泡,而是选择。

具体思路:也要进行6次循环。第一次循环,将2与后面的六个数进行比较,选出最小的即1放在第一个位置;下一次则是从第二个数开始,与后面的五个数进行比较,然后将第二小的数即2放在第二个位置;然后以此类推,直到排完为止。 

#include<iostream>
using namespace std;
int main() {
	int n,exchange;
	cout<<"要排几个数:";
	cin>>n;
	int a[100];
	for (int i=0; i<n; i++) {
		cin>>a[i];
	}
for(int i=0;i<=n;i++)
{
	for(int j=i+1;j<=n-1;j++)
	{
	if(a[i]>a[j])
	{exchange=a[i];
	a[i]=a[j];
	a[j]=exchange;
		
	}
		
	}
}
	for(int i=0; i<n; i++) {
		cout<<a[i]<<" ";
	}

}

快速排序 

快速排序可以说是比上面几个都不好理解的排序方法了。但它的效率却比较高思维方式也比较巧妙,需要用到二分法思想和递归。

这里参考了啊哈磊的文章,还是想要按照自己的语言来总结一下快速排序的算法,哈哈。

先看这样一个未排序之前的数列  6  1  2   7  9  3  4  5 10  8   ,然后再看一下它的变形:3  1  2 5  4  6  9 7  10  8。

会发现这十个数以6为基准分成了两个阵营:左边都比6小,右边都比6大。这里将6称为基准数,它将扮演重要的角色。

快速排序正是这样一个利用基准数不断分阵营的过程。咱们先看上面两个数列是如何变换的:

(图片源自于啊哈磊博客,侵删。)

 首先假如选择6作为基准数,并定义两个小兵(变量)i和j。初始值分别为1和10,即分别位于该数列的左右两边。

接下来分别交给这两个小兵不同的任务:小兵 j 先出发,向左走j--,它的任务是寻找比基准数6小的数,当它走到5这里时停住了;

小兵i然后出发,向右走i++,它的任务是寻找比基准数6大的数,当它走到7这里时停住了;如图所示:

下一步要做的就是交换,交换小兵脚下的值,到这里,第一波交换结束。

紧接着,小兵j继续出发,执行之前的任务。这次它在4这里停了下来;小兵i也出发,它在9这里停了下来;同样,仍然需要交换,交换后如图所示:

紧接着j继续走 ,寻找比6小的数,它发现了3,于是它停住了;紧接着i开始出发,却在3这里偶遇了j;此次它们的任务还尚未结束,它们还需要将脚下的值与基准数6进行交换。

至此,任务完成。 这一组数变成了这样:3 1 2 5 4 6 9 7 10 8,以6为基准分别在两边站好了对。

所以,上面的方法掌握了下面的就不难办了。即利用递归,分别再在两边的两组数中寻找基准数。比如:左边的3 1 2 5 4 ,

以3作为这组数的基准数,按照上面的方法,如果没错的话,一波操作下来应该变成了2 1 3 5 4 .

接下来需要处理3左边的序列2 1和右边的序列5 4。对序2 1以2为基准数进行调整,处理完毕之后的序列为“1 2”,到此2已经归位。序列“1”只有一个数,也不需要进行任何处理。至此我们对序列“2 1”已全部处理完毕,得到序列是“1 2”。序列“5 4”的处理也仿照此方法。

最终即可得1 2  3 4 5 6   7 8 9    10.   

所以整个过程中不断更换基准数,不断的站队。

对上述过程中几个细节做一些解释:

  • 基准数的选取:
  • 小兵出发的先后:

附一下代码:

#include<iostream>
using namespace std;
int a[100],n;
void quicksort(int left,int right) {
	int i,j,t,temp;
	if(left>right)
		return;

	temp=a[left];
	i=left;
	j=right;
	while(i!=j) {
		while(a[j]>=temp&&j>i)
			j--;
		while(a[i]<=temp&&j>i)
			i++;
		if(i<j) {
			t=a[i];
			a[i]=a[j];
			a[j]=t;
		}
	}
	a[left]=a[i];
	a[i]=temp;

	quicksort(left,i-1);
	quicksort(i+1,right);

}
int main() {
	cout<<"排几个数:";
	cin>>n;
	for(int i=0; i<n; i++) {
		cin>>a[i];
	}
	quicksort(0,n-1);
	for(int i=0; i<n; i++) {
		cout<<a[i]<<" ";
	}
}

 

另外还有其他的快速排序的思路,贴个地址:挖坑填数+分治法 。这个思路也很好。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++之五种排序方法总结 的相关文章

  • eclipse 使用maven 构建springboot +全局异常与局部异常区别

    一 controller 局部异常 package com zzg springbootone controller import org springframework web bind annotation ExceptionHandl
  • 开启系统代理之后,Microsoft Store 等 UWP 应用无法联网

    解决方法 以管理员方式打开 Powershell 输入 foreach n in get appxpackage packagefamilyname checknetisolation loopbackexempt a n n 恢复命令 f
  • unity粒子系统简单常用功能介绍

    1 GameObject Create Other Particle System 2 选中 Particle System 可看到下列屬性 3 Particle System Duration 粒子持续时间 设定为5秒 不开启循环模式下粒
  • 分布式事务神器:Spring Cloud Alibaba Seata 实战解析

    catalog 摘要 引言 官网 背景与挑战 Seata 的崛起 深入分析 Seata 核心概念解析 事务模式探索 快速上手 Seata 环境准备 分布式事务示例 高级应用与实践 Seata 集群部署与高可用性 自定义扩展与适配 性能优化与
  • (94)Verilog实现计数器

    94 Verilog实现计数器 1 1 目录 1 目录 2 FPGA简介 3 Verilog HDL简介 4 Verilog实现计数器 5 结语 1 2 FPGA简介 FPGA Field Programmable Gate Array 是
  • [leetcode: Python]389. Find the Difference

    题目 Given two strings s and t which consist of only lowercase letters String t is generated by random shuffling string s
  • 开源路上的酸甜苦辣

    多年前决定开源时 我们挺兴奋的 作为典型码农 用 开源是日常 而全力投入 做 开源 对我们绝大部分人都是头一遭 我们也曾天真地以为 开源 能有多难呢 不就是把代码放出去 大家一起用 一起写嘛 但是 开源 这事儿真的是这样子么 还是先看几个灵
  • #include <math.h>中sin,cos函数的使用

    在使用QT的时候遇到绘制类似仪表盘的问题 要定位仪表盘上刻度的坐标然后进行刻度线的绘制 需要把仪表盘角度等分 然后通过角度正余弦函数sin cos函数获得刻度线的坐标 math h中的sin和cos等函数的入参原型如下 double sin
  • 电池防反电路

    通常情况下直流电源输入防反接保护电路是利用二极管的单向导电性来实现防反接保护 如下图1示 图1 串联二极管保护系统不受反向极性影响 二极管有0 7V的压降 这种接法简单可靠 但当输入大电流的情况下功耗影响是非常大的 以输入电流额定值达到2A
  • Linux内核(5) - 内核学习的相关资源

    世界上最缺的不是金钱 而是资源 当我在一份报纸上看到这句大大标题时 我的第一反应是 作者一定是个自然环保主义者 然后我在羞愧得反省自身的同时油然生出一股对这样的无产主义理想者无比崇敬的情绪来 于是 我继续往下看 因此在XXX还未正式面市之时
  • sql之dml语句,语法和思路

    这些都是我自学时手打到文本文档 在复制粘贴到博客的 有一些命令格式不对 但全部百分百原创 如果有疑问或者不对的地方 欢迎评论区指正 也可以加q群592383030来探讨 我就是自学的普通人 不卖课 不涉及补习机构 我会出一整套mysql的学
  • OSS设置CORS规则以后还是报No 'Access-Control-Allow-Origin'解决方法

    OSS设置CORS规则以后还是报No Access Control Allow Origin 解决方法 在OSS控制台设置了CORS规则以后 通过JS程序去调用的时候报No Access Control Allow Origin heade
  • 合并两个数组为有序数组:

    合并两个数组为有序数组 思路 先合并再排序 数组的合并 利用 System arraycopy 方法实现数组复制 1 System中提供了一个native静态方法arraycopy 可以使用这个方法来实现数组复制 2 public stat
  • Anaconda打开Navigator报错-Navigator Error An unexpected error occurred on Navigator start-up

    问题如图 Windows下 1 使用管理员运行 conda prompt 2 执行命令 conda update anaconda navigator 3 还是不行就试试命令 anaconda navigator reset 来源 Navi
  • Opencv contours找出最大轮廓

    在处理二值图像时 常用 cv2 findContours 查找轮廓 如下所示 find all contours contours hierarchy cv2 findContours binary cv2 RETR TREE cv2 CH
  • vue前端缓存问题解决方案

    问题描述 大家用vue脚手架搭建前端工程时 常被缓存问题所困扰 具体的表现就是 当程序版本升级时 用户因为缓存访问的还是老的页面 然后很多同学很暴力的直接在index html中加入了这几行代码 升级时缓存问题倒解决了 但直接导致了用户每次
  • 用Eclipse创建第一个Spring项目(最最入门级)

    网上关于Spring的介绍资料已经数不胜数 但大多篇幅冗长 初学者不易理解记忆 这里先作一个简短的提炼 不作详细解释 主要内容是带大家创建一个Spring项目 感受一下这东西到底是什么样的 1 Spring Framework是用来干嘛的
  • 高效实现数据仓库的七个步骤

    高效实现数据仓库的七个步骤 数据仓库和我们常见的RDBMS系统有些亲缘关系 但它又有所不同 如 果你没有实施过数据仓库 那么从设定目标到给出设计 从创建数据结构到编写数据分析程序 再到面对挑剔的用户的评估 整个过程都会带给你一种与以往的项目
  • Hbase常用SQL命令

    这里写目录标题 Hbase常用SQL命令 1 启动hbase 2 进入hbase 3 hbase查看数据表 4 hbase建表语句 5 hbase禁用表 启用表 6 hbase添加单行数据 7 hbase文档添加数据 8 hbase扫描表

随机推荐

  • 分块矩阵求行列式

    分块矩阵求行列式 注意 第二个公式有误 将矩阵写为 P A B B A 那么det P det A det A BA 1B def A BA 1B a 1 1 A a b1 B a b2 a 0或a 1均可构造无穷多解 def A det
  • 基于Redis的原子操作优化秒杀逻辑

    对于缓存中间件Redis 相信各位小伙伴或多或少都有听说过 甚至实战过 本文我们将基于SpringBoot整合Redis中间件 并基于其优秀的 单线程 特性和原子操作实现一种 分布式锁 进而控制 高并发情况下多线程对于共享资源的访问 最终解
  • 递归法取硬币java_递归算法

    递归算法 在函数或子过程的内部 直接或者间接地调用自己的算法 特点 1 递归就是在过程或函数里调用自身 2 在使用递归策略时 必须有一个明确的递归结束条件 称为递归出口 3 递归算法解题通常显得很简洁 但递归算法解题的运行效率较低 所以一般
  • 线程池合理估算大小

    分配线程池究竟设置多大还是要看你的执行的任务 不要单方面看 线程任务分为Cpu密集型和IO密集型 混合型 主要看系统运行的任务是什么类型的 主要分为3种类型任务 CPU密集型和IO密集型 混合型任务 cpu密集型 一般分配N 1 什么是cp
  • Java 面试题(什么是分布式架构)

    Java 的分布式架构是指将应用程序分为不同的部分 这些部分可分别部署在不同的计算机上 它们相互之间通过网络进行通信和协作 从而共同完成某些任务 分布式应用程序通常需要满足以下几个特点 1 模块化 将应用程序模块化 将不同的功能放在独立的模
  • idea2022.2.2体验

    IntelliJ IDEA 2022 2 最新变化 IntelliJ IDEA 2022 2 为远程开发功能带来了多项质量改进 使其更美观 更稳定 从 v2022 2 开始 IntelliJ IDEA 使用 JetBrains Runtim
  • Java 构造方法与静态方法全解析

    构造方法 作用 一个类 可以有多个构造函数 构造函数的主要作用 一是用来实例化该类 二是 让该类实例化的时候执行哪些方法 初始化哪些属性 注意事项 如果你没写无参构造方法 系统会给你提供一个无参构造方法 如果只写了有参的构造方法 这时系统不
  • QT信号和槽参数传递

    写了一个这样的信号 void caculateReady QList
  • 异常检测专栏(三)传统的异常检测算法——上

    前言 在上一篇推文中 我们简要介绍了异常检测常用的几种数据集如ImageNet CIFAR10 CIFAR100 MNIST等 接下来 我们将基于传统的异常检测算法分为上 下两部分 逐一介绍不同类别的方法 本教程禁止转载 同时 本教程来自知
  • 基于 Postman 接口自动化场景设计

    一个强大的工具 基于 Postman 接口自动化场景设计 使用Xmind或者Yaml 设计 postman 自动化场景 引言 postman是一个比较轻量级的接口测试工具 在单个接口的测试表现优秀 在批量测试接口方面则提供了Runner C
  • ajax数据类型json,Ajax请求不与数据类型“jsonp”或“JSON”

    我想使用JSON作为Ajax请求 使用jQuery 的返回类型 但我的代码总是导致错误 我试过改变json和jsonp之间的MIME类型 但无济于事 Ajax请求不与数据类型 jsonp 或 JSON 我也不确定是否正确格式化数据 部分 我
  • 如何让HTTPS站点评级达到A+? 还得看这篇HTTPS安全优化配置最佳实践指南

    文章目录 0x00 前言简述 SSL TLS 简单说明 SSL TLS 相关术语一览 0x01 HTTPS安全实践指南 1 证书 certificate 与私钥 Private key 2 中间件SSL TLS服务器配置 3 SSL TLS
  • [news] Lion: The Complete Macworld Review

    the complete version is from http www macworld com article 161026 2011 07 osx lion review html In a decade Mac OS X evol
  • js常用数组操作方法

    1 concat 用于连接两个或多个数组 该方法不会改变现有的数组 仅会返回被连接数组的一个副本 2 join 用于把数组中的所有元素放入一个字符串 元素是通过指定的分隔符进行分隔的 默认使用 号分割 不改变原数组 3 push 可向数组的
  • 【QT开发笔记-基础篇】

    本节对应的视频讲解 B 站 链 接 QT开发笔记 基础篇 第二章 常用控件 2 12 表格控件 QTableWidget 1 QTableWidget 是 Qt 中的表格控件 可以行列的形式来展示数据 1 属性和方法 QTableWidge
  • 白话操作系统1.1 - CPU - virtualization - 虚拟

    1 桃子之影分身 three easy pieces操作系统一书中 教授谈起了分桃子的事情 说实际只有一个桃子 但却要分给很多猴子 那么问题来了 如何让每个猴子都能开开心心的分到桃呢 其实就是用一些手段啊 捏造出虚拟的桃子 虚拟的东西嘛 可
  • ECharts的讲解

    目录 什么是数据可视化 ECharts的介绍 ECharts的特点 ECharts的基本使用 操作步骤 通用配置title的相关配置 通用配置tooltip的相关配置 触发类型 trigger 触发时机 triggerOn 格式化 form
  • python 概率分布_Python中的联合概率分布

    要通过numpy中的m矩阵生成 可以将两个适当形状的数组相乘 如果数组x是1的n 而数组y是 则它们的乘积x y将是n 由m 在 下面是一个例子 说明如何用最初是一维的数据来处理这个问题 我使用随机值 如果是概率分布的话 应该对其进行规范化
  • 用Hexo制作自己的静态博客

    博客是一个老东西了 如果我们想写博客的话 有两种选择 第一种是在博客网站上 例如QQ空间 新浪博客 简书等网站上申请账号 然后编写博客 第二种就是自己找服务器搭一个博客 搭建博客也有两种选择 第一种是搭建动态博客 这方面最流行的就是Word
  • C++之五种排序方法总结

    模板函数sort sort是一个模板函数 sort 括号里可以接受两个或三个参数 这里先说一下两个参数的 因为三个参数的还没研究好 哈哈 使用sort 时需要添加头文件