C++-排序算法详解
目录
一. 冒泡排序:
二. 插入排序:
三. 快速排序:
四. 选择排序
五, 归并排序
六, 堆排序.
排序算法是一种将一组数据按照特定顺序(如升序或降序)进行排列的算法。
其主要目的是对一组无序的数据进行整理,使得它们呈现出一定的有序性。这样做有很多好处,比如:
- 方便查找和检索数据,提高搜索效率。
- 使数据更易于理解和分析。
- 在某些情况下,可以优化其他算法的性能。
主要排序算法有:冒泡排序.插入排序,快速排序.选择排序,归并排序,堆排序.
排序 | 优点 | 缺点 |
冒泡排序 | 简单易懂,容易实现 | 效率相对较低 |
插入排序 | 对于接近有序的数据效率较高 | 处理大规模无序数据时性能可能不太理想。 |
快速排序 | 平均性能较好,在大多数情况下效率较高 | 最坏情况下(比如已经有序或逆序)的性能会退化。 |
选择排序 | 算法简单直观,易于理解和实现。 | 它的比较次数较多,性能相对不是特别高 |
归并排序 | 具有稳定的性能,时间复杂度在最坏、平均和最好情况下都是O(nlogn) | 需要额外的空间来进行合并操作 |
堆排序 | 在最坏情况下性能也较好 | 不太稳定。 |
一. 冒泡排序:
冒泡排序的优点是简单易懂,容易实现。缺点是效率相对较低,尤其是对于基本有序的数组,仍然需要进行大量的比较和交换操作。
冒泡排序是一种简单直观的排序算法。
基本原理:
- 它通过反复比较相邻的元素,如果顺序不对则进行交换,并将最大的元素逐步“冒泡”到数组的末尾。
- 经过一轮比较交换后,最大的元素就会处于正确位置,然后对剩余未排序部分重复这个过程,直到整个数组都被排序。
以下是对冒泡排序过程的详细解释:
假设要排序的数组为 arr[n]
:
- 从数组的第一个元素开始,比较相邻的元素。如果前一个元素大于后一个元素,就交换它们的位置。
- 对整个数组进行这样的比较和交换操作,完成后,最大的元素就会“浮”到数组的末尾。
- 忽略已经排序好的最后一个元素,对剩下的元素重复步骤 1 和 2。
- 不断重复这个过程,直到整个数组都被排序。
以下是冒泡排序的 C++ 代码示例:
#include <iostream>void bubbleSort(int arr[], int n) {for (int i = 0; i < n - 1; i++) {for (int j = 0; j < n - i - 1; j++) {if (arr[j] > arr[j + 1]) {int temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}
}int main() {int arr[] = {64, 34, 25, 12, 22, 11, 90};int n = sizeof(arr) / sizeof(arr[0]);bubbleSort(arr, n);for (int i = 0; i < n; i++) {std::cout << arr[i] << " ";}return 0;
}
二. 插入排序:
插入排序的优点是对于接近有序的数据效率较高,所需的比较和交换操作相对较少。缺点是在处理大规模无序数据时性能可能不太理想。
基本原理:
它逐个将元素插入到已排序的部分中,以达到整个序列有序的目的。
具体步骤如下:
- 从第二个元素开始,将当前元素与已排序部分从后往前依次比较。
- 如果当前元素小于比较的元素,就将比较的元素向后移动一位。
- 一直重复这个过程,直到找到合适的位置插入当前元素。
- 然后继续处理下一个未排序的元素,重复上述操作,直到所有元素都被插入到合适位置。
下面是插入排序的 C++ 代码示例:
#include <iostream>void insertionSort(int arr[], int n) {for (int i = 1; i < n; i++) {int key = arr[i];int j = i - 1;while (j >= 0 && arr[j] > key) {arr[j + 1] = arr[j];j = j - 1;}arr[j + 1] = key;}
}int main() {int arr[] = { 12, 11, 13, 5, 6 };int n = sizeof(arr) / sizeof(arr[0]);insertionSort(arr, n);for (int i = 0; i < n; i++) {std::cout << arr[i] << " ";}return 0;
}
三. 快速排序:
快速排序的优点是平均性能较好,在大多数情况下效率较高。但它在最坏情况下(比如已经有序或逆序)的性能会退化。
基本原理:
- 选择一个基准元素。
- 将数组分为两个子数组,一个子数组中的元素都小于等于基准元素,另一个子数组中的元素都大于基准元素。
- 对这两个子数组分别进行快速排序。
具体步骤:
- 选择数组中的一个元素作为基准(通常选择第一个或最后一个元素)。
- 通过一趟排序将数组分为两部分,使得基准左边的元素都小于基准,右边的元素都大于基准。
- 对基准左边和右边的子数组分别递归地进行快速排序,直到整个数组有序。
以下是一个快速排序的 C++ 代码示例:
#include <iostream>// 交换两个元素
void swap(int* a, int* b) {int temp = *a;*a = *b;*b = temp;
}// 划分函数
int partition(int arr[], int low, int high) {int pivot = arr[high];int i = (low - 1);for (int j = low; j <= high - 1; j++) {if (arr[j] <= pivot) {i++;swap(&arr[i], &arr[j]);}}swap(&arr[i + 1], &arr[high]);return (i + 1);
}// 快速排序函数
void quickSort(int arr[], int low, int high) {if (low < high) {int pi = partition(arr, low, high);quickSort(arr, low, pi - 1);quickSort(arr, pi + 1, high);}
}int main() {int arr[] = { 12, 11, 13, 5, 6 };int n = sizeof(arr) / sizeof(arr[0]);quickSort(arr, 0, n - 1);for (int i = 0; i < n; i++) {std::cout << arr[i] << " ";}return 0;
}
四. 选择排序
选择排序的优点是算法简单直观,易于理解和实现。缺点是它的比较次数较多,性能相对不是特别高,尤其是对于较大规模的数据。例如,对于一个包含n
个元素的数组,它需要进行大约n^2/2
次比较。
基本原理:
在未排序的序列中不断地选择最小(或最大)元素,并将其放到已排序序列的末尾。
具体步骤:
- 从整个数组的第一个元素开始,遍历所有未排序的元素,找出其中最小(或最大)的元素。
- 将找到的最小(或最大)元素与数组的第一个未排序元素交换位置。
- 此时第一个元素就已排序,然后从第二个未排序元素开始重复上述过程,直到整个数组都被排序。
以下是选择排序的 C++代码示例:
#include <iostream>void selectionSort(int arr[], int n) {for (int i = 0; i < n - 1; i++) {int min_idx = i;for (int j = i + 1; j < n; j++) {if (arr[j] < arr[min_idx]) {min_idx = j;}}if (min_idx != i) {int temp = arr[i];arr[i] = arr[min_idx];arr[min_idx] = temp;}}
}int main() {int arr[] = { 12, 11, 13, 5, 6 };int n = sizeof(arr) / sizeof(arr[0]);selectionSort(arr, n);for (int i = 0; i < n; i++) {std::cout << arr[i] << " ";}return 0;
}
五, 归并排序
归并排序的优点是具有稳定的性能,时间复杂度在最坏、平均和最好情况下都是O(nlogn)。缺点是需要额外的空间来进行合并操作。
基本原理:
将数组不断地分成两半,对每一半进行排序,然后再将排序好的两半合并起来。
具体步骤如下:
- 把数组分成两半。
- 对左右两部分分别递归地进行归并排序。
- 将已经排序好的左右两部分合并为一个有序的数组。
在合并过程中,通过比较左右两部分的元素,依次将较小的元素放入新的合并后的数组中。
以下是归并排序的 C++ 代码示例:
#include <iostream>
#include <vector>// 合并函数
void merge(std::vector<int>& arr, int l, int m, int r) {int n1 = m - l + 1;int n2 = r - m;std::vector<int> left(n1), right(n2);for (int i = 0; i < n1; i++)left[i] = arr[l + i];for (int j = 0; j < n2; j++)right[j] = arr[m + 1 + j];int i = 0, j = 0, k = l;while (i < n1 && j < n2) {if (left[i] < right[j])arr[k++] = left[i++];elsearr[k++] = right[j++];}while (i < n1)arr[k++] = left[i++];while (j < n2)arr[k++] = right[j++];
}// 归并排序函数
void mergeSort(std::vector<int>& arr, int l, int r) {if (l < r) {int m = l + (r - l) / 2;mergeSort(arr, l, m);mergeSort(arr, m + 1, r);}
}int main() {std::vector<int> arr = { 12, 11, 13, 5, 6, 7, 8, 9, 10 };mergeSort(arr, 0, arr.size() - 1);for (int i = 0; i < arr.size(); i++) {std::cout << arr[i] << " ";}std::cout << std::endl;return 0;
}
六, 堆排序.
堆排序是一种选择排序。
堆排序的时间复杂度为O(n log n) ,空间复杂度为O(1) 。它的优点是在最坏情况下性能也较好,缺点是不太稳定。
基本概念:
堆是一种特殊的数据结构,可以分为大顶堆和小顶堆。大顶堆中每个节点的值都不小于其孩子节点的值,小顶堆则相反。
原理:
- 先将数组构建成一个大顶堆。
- 不断地将堆顶元素(最大值)与未排序部分的最后一个元素交换,然后调整堆,使其重新成为大顶堆。
具体步骤:
- 构建大顶堆:从最后一个非叶子节点开始,依次进行调整,使每个节点及其子树都满足大顶堆的性质。
- 排序过程:
- 将堆顶元素和未排序部分的最后一个元素交换。
- 对堆顶进行调整,使其重新成为大顶堆。
以下是堆排序的 C++ 代码示例:
#include <iostream>// 调整堆
void heapify(int arr[], int n, int i) {int largest = i;int l = 2 * i + 1;int r = 2 * i + 2;if (l < n && arr[l] > arr[largest])largest = l;if (r < n && arr[r] > arr[largest])largest = r;if (largest!= i) {std::swap(arr[i], arr[largest]);heapify(arr, n, largest);}
}// 堆排序函数
void heapSort(int arr[], int n) {for (int i = n / 2 - 1; i >= 0; i--)heapify(arr, n, i);for (int i = n - 1; i > 0; i--) {std::swap(arr[0], arr[i]);heapify(arr, i, 0);}
}int main() {int arr[] = {12, 11, 13, 5, 6};int n = sizeof(arr) / sizeof(arr[0]);heapSort(arr, n);for (int i = 0; i < n; i++) {std::cout << arr[i] << " ";}return 0;
}
相关文章:

C++-排序算法详解
目录 一. 冒泡排序: 二. 插入排序: 三. 快速排序: 四. 选择排序 五, 归并排序 六, 堆排序. 排序算法是一种将一组数据按照特定顺序(如升序或降序)进行排列的算法。 其主要目的是对一组无序的数据进行整理&#…...

Kotlin 引用(双冒号::)
文章目录 双冒号::引用函数普通函数成员函数类构造函数 引用变量(很少用)普通变量成员变量 双冒号:: Kotlin 中可以使用双冒号::对某一变量、函数进行引用。 Note:MyClass::class可用于获取KClass<MyClass>,此时的双冒号::…...

C++ day3练习
设计一个Per类,类中包含私有成员:姓名、年龄、指针成员身高、体重,再设计一个Stu类,类中包含私有成员:成绩、Per类对象p1,设计这两个类的构造函数、析构函数。 #include <iostream>using namespace std;class Per{private:…...

命令模式(行为型)
目录 一、前言 二、命令模式 三、总结 一、前言 命令模式(Command Pattern)是一种行为型设计模式,命令模式将一个请求封装为一个对象,从而可以用不同的请求对客户进行参数化;对请求排队或记录请求日志,以…...

韩雪医生针药结合效果好 患者赠送锦旗表感谢
任先生长年献血身体出现不适,身上多处发黑发冷,伴随疼痛,而且还有慢性腹泻的症状。他曾前往苏州各大医馆做过检查,均查不出异常,但身体确实不舒服,面色晦暗。 后来他来到李良济,求诊于韩雪医生。…...

【队列、堆、栈 解释与区分】
文章目录 概要队列(Queue)定义特性应用场景 堆(Heap)定义特性应用场景 栈(Stack)定义特性应用场景 总结 概要 队列、堆和栈是三种常见的数据结构,它们各自具有不同的特性和应用场景。下面是对这…...

NTP网络时间服务器_安徽京准电钟
NTP网络时间服务器_安徽京准电钟 NTP网络时间服务器_安徽京准电钟 概述 NTP网络时间服务器是一款支持NTP和SNTP网络时间同步协议,高精度、大容量、高品质的高科技时钟产品。 NTP网络时间服务器设备采用冗余架构设计,高精度时钟直接来源于北斗、GPS系统中…...

Java:爬虫框架
一、Apache Nutch2 【参考地址】 Nutch 是一个开源Java 实现的搜索引擎。它提供了我们运行自己的搜索引擎所需的全部工具。包括全文搜索和Web爬虫。 Nutch 致力于让每个人能很容易, 同时花费很少就可以配置世界一流的Web搜索引擎. 为了完成这一宏伟的目标, Nutch必须能够做到…...

ChatGPT基本原理详细解说
ChatGPT基本原理详细解说 引言 在人工智能领域,自然语言处理(NLP)一直是研究的热点之一。随着技术的发展,我们见证了从简单的聊天机器人到复杂的语言模型的演变。其中,ChatGPT作为一项突破性技术,以其强大…...

Java日期时间处理深度解析:从Date、Calendar到SimpleDateFormat
粉丝福利:微信搜索「万猫学社」,关注后回复「电子书」,免费获取12本Java必读技术书籍。 Java中的日期和时间处理 在Java中,日期和时间的处理一直是一个复杂而繁琐的任务。那么,为什么会这样呢?让我们先来看…...

Flutter 中的 CupertinoUserInterfaceLevel 小部件:全面指南
Flutter 中的 CupertinoUserInterfaceLevel 小部件:全面指南 Flutter 是一个功能强大的 UI 框架,由 Google 开发,允许开发者使用 Dart 语言构建跨平台的移动、Web 和桌面应用。在 Flutter 的 Cupertino(iOS 风格)组件…...

区块链学习记录01
在学习过程中所遇到的问题,及其解。 Q:区块链中分布式账本的存在,让所有人都知道资金的变动吗? A:区块链中的分布式账本确实让参与网络的所有节点都能够了解账户之间的资金变动。这是因为区块链是一个分布式数据库,其中包含着所…...

python--装饰器
[掌握]装饰器入门 语法糖 目标:掌握装饰器的快速使用。 装饰器本质上就是闭包,但装饰器有特殊作用,那就是:在不改变原有函数的基础上,给原有函数增加额外功能。 定义装饰器: def outer([外面参数列表]):…...

Docker:定义未来的软件部署
1. 概述 Docker,这个在技术圈里频频被提及的名词,实际上是一种开源的容器化技术。它允许开发者将应用程序及其依赖打包成一个标准化的单元——容器,确保应用在任何环境中都能够一致地运行。从开发者的本地机器到全球的云平台,Doc…...

ros常用环境变量
RMW层DDS实现 rti dds export RMW_IMPLEMENTATIONrmw_connextdds //rti dds 或者 RMW_IMPLEMENTATIONrmw_connextdds ros2 run ... export NDDS_QOS_PROFILES/qos.xml //配置qos文件fastdds export RMW_IMPLEMENTATIONrmw_fastrtps_cpp 或者 RMW_IMPLEMENTATIONrmw_fas…...

python学习 - 爬虫案例 - 爬取链接房产信息入数据库代码实例
#codingutf-8 #!/usr/bin/python # 导入requests库 import requests # 导入文件操作库 import os import re import bs4 from bs4 import BeautifulSoup import sys from util.mysql_DBUtils import mysql# 写入数据库 def write_db(param):try:sql "insert into house (…...

Git 完整操作之记录
目录 一 . Git 基本操作流程及示例代码 1. 初始化 Git 仓库 2. 克隆远程仓库 3. 检查当前状态 4. 添加文件到暂存区 5. 提交更改 6. 查看提交历史 7. 创建分支 8. 切换分支 9. 合并分支 10. 推送更改到远程仓库 11. 拉取远程仓库的更改 12. 回滚到上一个版本 二…...

mediaPlayer的内存泄露解决方法
MediaPlayer在Android中用于播放音频和视频。如果不正确管理,MediaPlayer可能会导致内存泄漏,尤其是当它被用于多个Activity或长时间播放时。以下是一些解决MediaPlayer内存泄漏的方法: ### 1. 及时释放资源 当MediaPlayer不再使用时&#x…...

delphi3层 delphi 3层
一、为DataSnap系统服务程序添加描述 procedure TServerContainer.ServiceAfterInstall(Sender: TService); var reg: TRegistry; begin reg : TRegistry.Create; try with reg do begin RootKey : HKEY_LOCAL_MACHINE; if OpenKey(SYSTEM/CurrentC…...

Python编程学习第一篇——制作一个小游戏休闲一下
到上期结束,我们已经学习了Python语言的基本数据结构,除了数值型没有介绍,数值型用的非常广,但也是最容易理解的,将在未来的学习中带大家直接接触和学习掌握。后续我们会开始学习这门语言的一些基础语法和编程技巧&…...

03--nginx架构实战
前言:这应该是nginx梳理的最后一章,写一些关于网站架构和网站上线的知识内容,主要是感觉到运维并不是单一方向的行业,这一章概念会有一些广泛,但是非常重要,都是这几年工作中遇到的情况,整理一下…...

【力扣第 400 场周赛】Leetcode 删除星号以后字典序最小的字符串
文章目录 1. 删除星号以后字典序最小的字符串 1. 删除星号以后字典序最小的字符串 题目链接 🍎 解题思路:遇到 *就删除一个字符,为了满足题意,要删除字典序最小的字符,那么假如有多个字典序最小的字符我们该删除哪个…...

Unity DOTS技术(九) BufferElement动态缓冲区组件
文章目录 一.简介二.例子 一.简介 在之前的学习中我们发现Entity不能挂载相同的组件的. 当我们需要用相同的组件时则可以使用.IBufferElementData接口 动态缓冲区组件来实现 二.例子 1.创建IBufferElementData组件 using Unity.Entities; using UnityEngine; //[GenerateAu…...

hnust 湖南科技大学 2022 软件测试报告+代码
hnust 湖南科技大学 2022 软件测试报告代码 内容 BMI junit单元测试决策表划分方法测试三角形判断问题文档修改问题之因果图实验逻辑覆盖测试技术实验(白盒测试)selenium 功能自动化测试Jmeter 性能自动化测试 下载地址 https://pan.baidu.com/s/19e…...

【面试笔记】单片机软件工程师,工业控制方向(储能)
文章目录 1. 基础知识1.1 C语言笔试题1.1.1 用宏定义得到一个数组所含的元素个数1.1.2 定义函数指针从程序固定地址(0)开始执行1.1.3 volatile的含义及作用1.1.4 32位系统,整数7和-7,分别以大端和小端存储,请示意说明 1.2 嵌入式基础1.2.1 简…...

基于springboot实现小区团购管理系统项目【项目源码+论文说明】计算机毕业设计
基于springboot实现小区团购管理系统演示 摘要 传统办法管理信息首先需要花费的时间比较多,其次数据出错率比较高,而且对错误的数据进行更改也比较困难,最后,检索数据费事费力。因此,在计算机上安装小区团购管理软件来…...

基于django | 创建数据库,实现增、删、查的功能
1、在cmd中,输入指令进入mysql终端: mysql -u 用户名 -p 2、输入mysql的密码 3、输入指令,显示出所有的数据库 show databases; 4、输入指令创建表: create table 表名 DEFAULT CHARSET utf8 COLLATE utf8_general_ci; 5、use …...

数据结构与算法07-图
介绍 图是一种善于处理关系型数据的数据结构,使用它可以很轻松地表示数据之间是如何关联的。 图的实现形式有很多,最简单的方法之一就是用散列表。 friends { "Alice" > ["Bob", "Diana", "Fred"], &quo…...

springboot项目部署需要redis集群问题
本来直接将redis为单独启动模式转为配置 yml文件 spring.redis.cluster.nodes: 192.168.12.78:8001,192.168.12.78:8002,192.168.12.78:8003, java文件 package io.sirc.config;import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.ann…...

JVMの内存泄漏内存溢出案例分析
1、内存溢出 内存溢出指的是程序在申请内存时,没有足够的内存可供分配,导致无法满足程序的内存需求,常见的内存溢出情况包括堆内存溢出(Heap Overflow)和栈溢出(Stack Overflow): …...