当前位置: 首页 > 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;如果不能则传递给链上的下一个对象。为了避免请求发送者与多个请求处理者耦合在…...

JAVA8的新特性——Stream

JAVA8的新特性——Stream 在这个深夜写下这篇笔记&#xff0c;窗外很安静&#xff0c;耳机里是《季节更替》&#xff0c;我感触还不是很多&#xff0c;当我选择封面图片的时候才发现我们已经渐渐远去&#xff0c;我们都已经奔赴生活&#xff0c;都在拼命想着去换一个活法&#…...

alias设置快捷键vim使用说明(解决服务器上输入长指令太麻烦的问题)

1. vi ~/.bashrc打开 2. (watch -n 1 gpustat 查看gpu使用情况 太麻烦)输入i进行编辑&#xff0c;最后一行输入 alias watchgpuwatch -n 1 gpustat alias gpuwatch -n 1 gpustat alias torch180source activate torch180 3. 按esc&#xff0c;然后输入:wq保存退出 4. source…...

英语基础句型之旅:从基础到高级

英语句型之旅&#xff1a;从基础到高级 一、起步&#xff1a;掌握英语基础句型 (Getting Started: Mastering Basic English Sentence Structures)1.1 英语句子的基本构成 (The Basic Components of English Sentences)1.2 五大基本句型解析 (Analysis of the Five Basic Sente…...

十四、Zuul网关

目录 一、API网关作用&#xff1a; 二、网关主要功能&#xff1a; 2.1、统一服务入口 2.2、接口鉴权 2.3、智能路由 2.4、API接口进行统一管理 2.5、限流保护 三、 新建一个项目作为网关服务器 3.1、项目中引入Zuul网关依赖 3.2、在项目application.yml中配置网关路由…...

5项目五:W1R3S-1(思路为主!)

特别注明&#xff1a;本文章只用于学习交流&#xff0c;不可用来从事违法犯罪活动&#xff0c;如使用者用来从事违法犯罪行为&#xff0c;一切与作者无关。 目录 前言 一、信息收集 二、网页信息的收集 三、提权 总结 前言 思路清晰&#xff1a; 1.信息收集&#xff0c;…...

Day958.代码的分层重构 -遗留系统现代化实战

代码的分层重构 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于代码的分层重构的内容。 来看看如何重构整体的代码&#xff0c;也就是如何对代码分层。 一、遗留系统中常见的模式 一个学校图书馆的借书系统。当时的做法十分“朴素”&#xff0c;在点击“借阅”按钮…...

分子模拟力场

分子模拟力场 AMBER力场是在生物大分子的模拟计算领域有着广泛应用的一个分子力场。开发这个力场的是Peter Kollman课题组&#xff0c;最初AMBER力场是专门为了计算蛋白质和核酸体系而开发的&#xff0c;计算其力场参数的数据均来自实验值&#xff0c;后来随着AMBER力场的广泛…...

ERP 系统在集团化企业财务管理中的应用

&#xff08;一&#xff09;集团统一会计核算平台的构建原理及功能 第一&#xff0c;搭建集中统一会计核算平台的基础是确定财务组 织及岗位&#xff0c;在此基础上制定统一的会计核算政策、规范集中 基础数据、落实内控管理制度。 第二&#xff0c;具备了以上建立集中统一会计…...

达摩院开源多模态对话大模型mPLUG-Owl

miniGPT-4的热度至今未减&#xff0c;距离LLaVA的推出也不到半个月&#xff0c;而新的看图聊天模型已经问世了。今天要介绍的模型是一款类似于miniGPT-4和LLaVA的多模态对话生成模型&#xff0c;它的名字叫mPLUG-Owl。 论文链接&#xff1a;https://arxiv.org/abs/2304.14178…...

Group相关问题-组内节点限制移动范围

1.在节点中定义dragComputation,限制节点的移动范围 注意事项 组节点不定义go.Placeholder ,设置了占位符后组内节点移动将改变组节点位置dragComputation中自定义stayInGroup计算规则是根据groupNode的resizeObject计算 如果开启了resizable:true,建议指定其改变大的零部件r…...