当前位置: 首页 > news >正文

几种内部排序算法的cpp代码实现与分析

零、测试函数

typedef void (*SortFunc) (int*&, int);inline void swap(int &a, int &b) {int tmp = a;a = b;b = tmp;
}inline void printArr(int* a, int n) {for (int k = 0; k < n; ++k) {std::cout << a[k] << ' ';}std::cout << std::endl;
}void testSort(SortFunc func) {srand(time(nullptr));int n = rand() % 10 + 10;int* a = new int[n];for (int i = 0; i < n; ++i) {a[i] = rand() % 100;}printArr(a, n);(*func)(a, n);printArr(a, n);}

首先使用typedef将传参为(int*&, int),返回值为空的指向函数的指针类型命名为SortFunc。

其次,定义swap函数与printArr函数,swap函数会在冒泡排序、快速排序等排序算法中使用,而printArr用来输出数组。

最后,定义函数testSort,传参一个指向函数的指针,在函数体内,程序将生成一个长度取10~20之间的随机值,元素大小取0~100之间的随机值的一个数组。先对数组进行一次输出,然后调用参数func指向的函数对数组进行排序,再排序结果输出一次。

一、插入排序

插入排序的思想是每次都将一个待排序的元素按关键字大小插入前面已排序好的子序列。插入排序主要分为:直接插入排序、折半插入排序、希尔排序。

在数组已基本有序的前提下,插入排序效率最高。

1. 直接插入排序

void straightInsertionSort(int* &a, int n) {for (int i = 1; i < n; ++i) {if (a[i] >= a[i-1]) continue;int j;int tmp = a[i];for (j = i - 1; tmp < a[j] && j >= 0; --j) {a[j+1] = a[j];}a[j+1] = tmp;printArr(a, n);}}

空间复杂度:O(1)
时间复杂度:最好情况下为O(n),即数组已有序,只需进行一次遍历、最坏情况下为O(n2)、平均O(n2)
稳定性:具有稳定性

2. 折半插入排序

void binaryInsertionSort(int* &a, int n) {for (int i = 1; i < n; ++i) {if (a[i] >= a[i-1]) continue;int tmp = a[i];int low = 0;int high = i-1;int mid;while (low <= high) {mid = (low + high) / 2;if (a[mid] > tmp) {high = mid - 1;} else {low = mid + 1;}}for (int j = i; j > high+1; --j) {a[j] = a[j-1];}a[high+1] = tmp;printArr(a, n);}}

空间复杂度:O(1)
时间复杂度:最好情况下为O(n),即数组已有序,只需进行一次遍历、最坏情况下为O(n2)、平均O(nn)
稳定性:具有稳定性

3. 希尔排序

void shellSort(int* &a, int n) {int gap = n >> 1;int tmp, j;while (gap) {std::cout << "gap = " << gap << std::endl;for (int i = gap; i < n; ++i) {if (a[i] >= a[i-gap]) continue;tmp = a[i];for (j = i-gap; tmp < a[j] && j >= 0; j -= gap) {a[j+gap] = a[j];}a[j+gap] = tmp;printArr(a, n);}gap >>= 1;}}

空间复杂度:O(1)
时间复杂度:当n在某个特定范围内时,希尔排序的时间复杂度均为O(n1.3)。在最坏情况下希尔排序的时间复杂度为O(n2)。
稳定性:不具有稳定性
注意希尔排序仅适用于顺序存储的线性表

二、交换排序

1. 冒泡排序

void bubbleSort(int* &a, int n) {for (int i = 0; i < n - 1; ++i) {bool flag = true;for (int j = n - 1; j > i; --j) {if (a[j - 1] > a[j]) {swap(a[j-1], a[j]);flag = false;}}printArr(a, n);if (flag) {break;}}}

空间复杂度:O(1)
时间复杂度:最好情况下为O(n),即数组已有序,只需进行一次遍历、最坏情况下为O(n2)、平均O(n2)
稳定性:具有稳定性

2. 快速排序

void quickSort(int* &a, int high, int low = 0) {int i = low;int j = high - 1;if (i >= j) return;int pivot = a[i];while (i < j) {while (i < j && pivot < a[j]) j--;a[i] = a[j];while (i < j && a[i] < pivot) i++;a[j] = a[i];}a[i] = pivot;std::cout << "pivot = " << pivot << std::endl;quickSort(a, i, low);quickSort(a, high, i + 1);}

空间复杂度:由于快速排序是递归的,需要借助一个递归的工作栈来保存每层递归的必要信息,其容量与递归调用的最大深度保持一致。最好情况下为O(log2n);最坏情况下,即数组已有序,需要进行n-1次递归调用,空间复杂度为O(n)。平均空间复杂度为O(log2n)。

时间复杂度:最好情况下为O(nlog2n),最坏情况下为O(n2),平均为O(nlog2n)。

稳定性:不具有稳定性。

在大多数情况下,快速排序是平均性能最高的排序算法,但是排序算法并不适合对已基本接近有序的数组进行排序。

三、选择排序

1. 简单选择排序

void selectionSort(int* &a, int n) {int minIndex;for (int i = 0; i < n - 1; i++) {minIndex = i;for (int j = i + 1; j < n; j++) {if (a[j] < a[minIndex]) {minIndex = j;}}if (minIndex != i) {swap(a[i], a[minIndex]);}printArr(a, n);}}

空间复杂度:O(1)
时间复杂度:最好情况、最坏情况、平均情况下都为O(n2)
稳定性:不具有稳定性

2. 堆排序

void heapAdjust(int* &heap, int root, int n) {int tmp = heap[root]; // 暂存根节点for (int i = 2 * root + 1; i < n; i = i * 2 + 1) {if (i + 1 < n && heap[i] < heap[i+1]) {i++; // 如果右子结点更大,让指针对准右子结点}if (tmp >= heap[i]) {break;} else {heap[root] = heap[i];root = i;}}heap[root] = tmp;}void buildMaxHeap(int* &heap, int n) {for (int i = n / 2 - 1; i >= 0; --i) {heapAdjust(heap, i, n);}
}void heapSort(int* &a, int n) {buildMaxHeap(a, n);for (int i = n - 1; i > 0; --i) {swap(a[i], a[0]);heapAdjust(a, 0, i - 1);}
}

空间复杂度:O(1)
时间复杂度:建堆的时间复杂度为O(n),之后有n-1次向下调整,每次向下调整复杂度为O(h),h为堆的深度,约为log2n,故最好情况、最坏情况、平均情况下时间复杂度都为O(nlog2n)
稳定性:不具有稳定性

四、归并排序

static int* b;void merge(int* &a, int low, int mid, int high) {for (int i = low; i <= high; ++i) {b[i] = a[i];}int i, j, k;for (i = low, j = mid + 1, k = low; i <= mid && j <= high; k++) {if (b[i] <= b[j]) {a[k] = b[i++];} else {a[k] = b[j++];}}while (i <= mid) {a[k++] = b[i++];}while (j <= high) {a[k++] = b[j++];}}void mergeSort(int* &a, int low, int high) {if (low >= high) return;int mid = (low + high) / 2;mergeSort(a, low, mid);mergeSort(a, mid + 1, high);merge(a, low, mid, high);
}void mergeSort(int* &a, int n) {b = new int[n];mergeSort(a, 0, n-1);
}

空间复杂度:由于数组b的创建,空间复杂度为O(n)
时间复杂度:每趟归并复杂度为O(n)一共需要log2n次归并,所以复杂度为O(nlog2n)。
稳定性:具有稳定性。

五、基数排序

class ListNode {public:int data;ListNode* next;friend std::ostream & operator<< (std::ostream &out, ListNode &l) {ListNode* p = l.next;while(p) {out << p->data << ' ';p = p->next;}return out;}};void radixSort(ListNode* l, int d) {ListNode *p, *q;for (int i = 0; i < d; ++i) {ListNode* start[16];ListNode* end[16];bool flags[16];for (bool &flag : flags) {flag = false;}while (l->next) {p = l->next;l->next = p->next;p->next = nullptr;int x = p->data;int index = (x >> (4 * i)) & 0xf;if (flags[index]) {end[index]->next = p;end[index] = p;} else {start[index] = p;end[index] = p;flags[index] = true;}}q = l;for (int j = 0; j < 16; ++j) {if (flags[j]) {q->next = start[j];q = end[j];}}std::cout << *l << std::endl;}}

设r个队头指针队尾指针(上述代码中是16个),共进行d趟分配与收集。

空间复杂度:O®

时间复杂度:进行d趟分配与收集,一趟分配O(n),一趟收集O(r),时间复杂度为O(d(n+r))

稳定性:具有稳定性

六、总结

  1. 若n较小,可采用直接插入排序或简单选择排序。直接插入排序比较次数少移动次数多,简单选择排序比较次数多移动次数少。所以当记录的信息量较大时,更适合选用简单选择排序。
  2. 若文件初始状态已基本有序,应当使用直接插入排序或冒泡排序。
  3. 若n较大,则应该使用时间复杂度为O(nlog2n)的排序方法:快速排序、堆排序或归并排序,目前快速排序被认为是所有基于比较的排序算法中最好的算法,当待排序关键字随机分布时,快速排序所使用的平均时间最短。堆排序相比快速排序的优点是:不需要开辟额外的内存空间。但这两种算法都是不稳定的排序算法。并且当数据已基本有序时,快速排序效率较低,不宜使用。
  4. 若n很大,而记录的关键字位数比较少且可分解,宜采用基数排序。
  5. 当记录信息量较大,为避免耗费大量时间移动记录,可使用链表作为存储结构。

相关文章:

几种内部排序算法的cpp代码实现与分析

零、测试函数 typedef void (*SortFunc) (int*&, int);inline void swap(int &a, int &b) {int tmp a;a b;b tmp; }inline void printArr(int* a, int n) {for (int k 0; k < n; k) {std::cout << a[k] << ;}std::cout << std::endl; }…...

第3天学习Docker-Docker部署常见应用(MySQL、Tomcat、Nginx、Redis、Centos)

前提须知&#xff1a; &#xff08;1&#xff09;搜索镜像命令 格式&#xff1a;docker search 镜像名 &#xff08;2&#xff09;设置Docker镜像加速器 详见文章&#xff1a;Docker设置ustc的镜像源&#xff08;镜像加速器&#xff09; 1、部署MySQL 拉取镜像&#xff08;这…...

给大家介绍四款最受欢迎的抓包神器

身为互联网人&#xff0c;无论在平时开发还是在测试过程中&#xff0c;我们都不可避免的会涉及到网络安全性&#xff0c;如何监测网络请求&#xff0c;从而最大程度的保证数据的安全&#xff0c;需要我们了解并掌握抓包的技巧。那么何谓抓包呢&#xff1f;抓包就是将网络传输发…...

解决Reids过期方案 游标遍历清除Redis过期的key

游标遍历清除Redis过期的key 为什么要清除Redis过期的Key ​ Redis的过期清理是一种懒惰的清理方案&#xff0c;他不会过期后立刻清除&#xff0c;而是在Key被访问的时候进行删除&#xff0c;Redis这么做的目的就是为了提高性能降低资源开销。 ​ 具体来说&#xff0c;一个K…...

K8s基础10——数据卷、PV和PVC、StorageClass动态补给、StatefulSet控制器

文章目录 一、数据卷类型1.1 临时数据卷&#xff08;节点挂载&#xff09;1.2 节点数据卷&#xff08;节点挂载&#xff09;1.3 网络数据卷NFS1.3.1 效果测试 1.4 持久数据卷&#xff08;PVC/PV&#xff09;1.4.1 效果测试1.4.2 测试结论 二、PV、PVC生命周期2.1 各阶段工作原理…...

oracle系统查询~3

查看实例的基本信息 SQL> col host_name for a25 col instance_name for a15 col version for a15 col status for a10 set linesize 600 col host_name for a20 select instance_number,instance_name,host_name,version,startup_time,status,archiver f…...

Mybatis源码(九)— chche

Mybatis中共有三级缓存&#xff0c;其中一级缓存默认开启&#xff0c;作用范围是在sqlSession对象&#xff08;同一个会话&#xff09;&#xff0c;二级缓存需要手动配置开启&#xff0c;作用范围是在sqlSessionFactory对象下的同一个namespace范围&#xff08;所以二级缓存是可…...

回溯法--N皇后问题

N皇后问题 一、问题描述二、示例2.1 四皇后的2个可行解2.2 过程图示 三、问题分析3.1涉及到的概念递归回溯 3.2 分析 四、 代码实现4.1 实现思路宏观&#xff1a;微观&#xff1a; 4.2 递归函数NS图4.3 代码 一、问题描述 1、按照国际象棋的规则&#xff0c;皇后可以攻击与之处…...

ajax请求

ajax的优点 可以无需刷新页面而与服务器进行通信允许你根据用户事件来更新部分页面内容 ajax的缺点 没有浏览历史&#xff0c;不能回退存在跨域问题SEO不友好 get请求 <button>点击发送请求</button><div id"result"></div><script>…...

K8S系列之污点和容忍度详细分析

架构图 本篇文档主要介绍污点和容忍度的关系。 污点和容忍度 污点顾名思义就是脏的东西&#xff0c;给节点添加污点来限制pod调度到该节点上&#xff0c;如果pod可以容忍这种污点就可以被调度到有污点的节点上&#xff0c;如果不能容忍就不能被调度到该节点上。 污点作用于节…...

【算法】Minimum Moves to Move a Box to Their Target Location 推箱子

文章目录 Minimum Moves to Move a Box to Their Target Location 推箱子问题描述&#xff1a;分析代码 Tag Minimum Moves to Move a Box to Their Target Location 推箱子 问题描述&#xff1a; 问题 「推箱子」是一款风靡全球的益智小游戏&#xff0c;玩家需要将箱子推到仓…...

决策引擎平台建设方案

文档修订历史 时间版本主要内容2023.05.12v1.0.0初始化 1. 概述 1.1 需求 1.1.1 需求背景 当同一个业务场景中&#xff0c;有非常多的业务分支后&#xff0c;需要有非常多的 if 判断&#xff0c;来承载这些简单的业务逻辑&#xff0c;但随着业务的发展&#xff0c;业务逐渐…...

SpringBoot Starter 作用及原理

本文会以 mybatis 为例&#xff0c;通过对比 mybatis-spring 和 mybatis-spring-boot-starter 代码示例&#xff0c;了解 Starter 的作用。并对 mybatis-spring-boot-starter 进行简单剖析&#xff0c;了解 Starter 原理。 下面还有投票&#xff0c;一起参与进来吧&#x1f44d…...

【rust】| 05——语法基础 | 流程控制

系列文章目录 【rust】| 00——开发环境搭建 【rust】| 01——编译并运行第一个rust程序 【rust】| 02——语法基础 | 变量(不可变?)和常量 【rust】| 03——语法基础 | 数据类型 【rust】| 04——语法基础 | 函数 【rust】| 05——语法基础 | 流程控制 文章目录 流程控制1. 条…...

解决Makefile: recipe for target ‘xxx‘ failed

author daisy.skye的博客_CSDN博客-嵌入式,Qt,Linux领域博主 问题 在android编译Kernel调用makefile引起的recipe for target 很多文章写的是由于编译文件路径引起或者是makefile代码中的空格引起的 分析 但是如果makefile文件不是手动配置的而且源代码提供的&#xff0c;…...

小黑子—多媒体技术与运用基础知识三:数字图形图像处理技术

多媒体技术与运用3.0 多媒体系列第三章1. 颜色科学1.1 颜色的性质1.1.1 颜色的物理性质1.1.2颜色三特性1.1.3三原色与三补色 1.2 颜色空间1.2.1 与设备无关的颜色空间1.2.1 与设备相关的颜色空间 1.3 常见的多媒体系统颜色空间1.3.1 RGB颜色空间1.3.2 CMYK颜色模型1.3.3 HSB颜色…...

Nginx实现ChatGPT API代理

文章目录 一、前言说明二、前置准备三、nginx配置三、代理域名用途 一、前言说明 本篇文章可以直接用于公司生产级的使用&#xff0c;所需要的资源直接改为公司级的即可平替使用文章均已通过实践应用&#xff0c;保证文章准确性&#xff0c;但因不同环境的不同可能效果不一致可…...

FileNotFoundError: [Errno 2] No such file or directory: ‘dot‘

FileNotFoundError: [Errno 2] No such file or directory: ‘dot’ 在绘制树形结构图的时候出现上述报错&#xff1a;已安装环境为ubuntu&#xff0c;python3.9 解决方案&#xff1a; 1、在终端输入sudo apt-get install graphviz&#xff0c;按回车键&#xff0c;输入密码&a…...

【分布族谱】正态分布和二项分布的关系

文章目录 正态分布二项分布验证 正态分布 正态分布&#xff0c;最早由棣莫弗在二项分布的渐近公式中得到&#xff0c;而真正奠定其地位的&#xff0c;应是高斯对测量误差的研究&#xff0c;故而又称Gauss分布。测量是人类定量认识自然界的基础&#xff0c;测量误差的普遍性&am…...

7.设计模式之责任链模式

前言 责任链&#xff0c;即将能够处理同一类请求的对象连成一条链&#xff0c;所提交的请求沿着链传递&#xff0c; 链上的对象逐个判断是否有能力处理该请求&#xff0c;如果能则处理&#xff0c;如果不能则传递给链上的下一个对象。为了避免请求发送者与多个请求处理者耦合在…...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

Keil 中设置 STM32 Flash 和 RAM 地址详解

文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

HBuilderX安装(uni-app和小程序开发)

下载HBuilderX 访问官方网站&#xff1a;https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本&#xff1a; Windows版&#xff08;推荐下载标准版&#xff09; Windows系统安装步骤 运行安装程序&#xff1a; 双击下载的.exe安装文件 如果出现安全提示&…...

c#开发AI模型对话

AI模型 前面已经介绍了一般AI模型本地部署&#xff0c;直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型&#xff0c;但是目前国内可能使用不多&#xff0c;至少实践例子很少看见。开发训练模型就不介绍了&am…...

在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?

uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件&#xff0c;用于在原生应用中加载 HTML 页面&#xff1a; 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

深度学习习题2

1.如果增加神经网络的宽度&#xff0c;精确度会增加到一个特定阈值后&#xff0c;便开始降低。造成这一现象的可能原因是什么&#xff1f; A、即使增加卷积核的数量&#xff0c;只有少部分的核会被用作预测 B、当卷积核数量增加时&#xff0c;神经网络的预测能力会降低 C、当卷…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...