归并排序和计数排序

目录

  • 1.归并排序
    • 1.1递归
      • 1.1基本思想
      • 1.2算法描述
      • 1.3画图解释
      • 1.4代码实现
    • 1.2非递归
  • 2.计数排序
    • 2.1基本思想
    • 2.2算法描述
    • 3.画图解释

1.归并排序

1.1递归

在这里插入图片描述

1.1基本思想

归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
特性
时间复杂度:O(Nlog N)
空间复杂度:O(N)

归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题

1.2算法描述

  • 把长度为n的序列分为2个亮度为n/2的子序列
  • 对这2个子序列分别采用归并排序
  • 将2个排序好的子序列合成一个最终的排序序列

1.3画图解释

在这里插入图片描述

1.4代码实现

// 归并排序递归实现
void _MergeSort(int* a,int*tmp, int left,int right)
{//表示该区间只有一个元素或者该区间不存在if (left >= right)return;int mid = left + ((right - left) >> 1);//[left,mid] [mid+1,right]//如果有序就进行归并,没有序就继续分治_MergeSort(a,tmp, left, mid);_MergeSort(a,tmp, mid+1, right);//归并int begin1 = left;int begin2 = mid + 1;int i = left;while (begin1 <= mid && begin2 <= right){//两子序列比较大小if (a[begin1] < a[begin2]){tmp[i++] = a[begin1++];}else{tmp[i++] = a[begin2++];}}//两子序列其中一个序列走完了//1.假设第1个子序列走完了,将第2个子序列放入tmp数组中//2.假设第2个子序列走完了,将第1个子序列放入tmp数组中while (begin1 <= mid){tmp[i++] = a[begin1++];}while (begin2 <= right){tmp[i++] = a[begin2++];}//放入tmp数组完成//将tmp数组的数copy到a数组中memcpy(a+left, tmp+left, (right - left + 1) * sizeof(int));
}
void MergeSort(int* a, int n)
{//申请空间int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail");return;}//申请空间成功_MergeSort(a, tmp, 0, n - 1);free(tmp);tmp = NULL;
}

1.2非递归

  • 先11归并,再22归并,再44归并…以2的倍数进行归并
    在这里插入图片描述
// 归并排序非递归实现
void MergeSortNonR(int* a, int n)
{int* tmp = (int*)malloc(sizeof(int) * n);if (tmp == NULL){perror("malloc fail");return;}int gap = 1;while (gap < n){for (int i = 0; i < n; i += 2 * gap){int begin1 = i, end1 = i+ gap - 1;int begin2 = i + gap, end2 =i + 2 * gap - 1;int j = begin1;//如果第二组越界,第二组就不用归并了if (begin2 >= n){break;}//如果第二组只一部分越界,就修改第二组的范围if (end2 >= n){end2 = n - 1;}while (begin1 <= end1 && begin2 <= end2){//两子序列比较大小if (a[begin1] < a[begin2]){tmp[j++] = a[begin1++];}else{tmp[j++] = a[begin2++];}}//两子序列其中一个序列走完了//1.假设第1个子序列走完了,将第2个子序列放入tmp数组中//2.假设第2个子序列走完了,将第1个子序列放入tmp数组中while (begin1 <= end1){tmp[j++] = a[begin1++];}while (begin2 <= end2){tmp[j++] = a[begin2++];}//将tmp数组中元素copy到a数组中memcpy(a + i, tmp + i, (end2 - i + 1) * sizeof(int));}gap *= 2;}free(tmp);tmp = NULL;
}

2.计数排序

在这里插入图片描述

2.1基本思想

计数排序不是基于比较的排序算法,其核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。 作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。
特性:

  1. 计数排序在数据范围集中时,效率很高,但是适用范围及场景有限。
  2. 时间复杂度:O(MAX(N,范围))
  3. 空间复杂度:O(范围)

2.2算法描述

  • 找出待排序的数组中最大和最小的元素;
  • 统计数组中每一个值为i的元素出现的次数,存入新数组的第i项;
  • 对所有的计数累加;
  • 反向填充目标数组:将每个元素i放在新数组的第i项,每放一个元素就-1.

3.画图解释

在这里插入图片描述
在这里插入图片描述

// 计数排序
void CountSort(int* a, int n)
{//找最大,最小值int max =a[0];int min =a[0];for (int i = 1; i < n; i++){if (max < a[i])max = a[i];if (min > a[i])min = a[i];}//申请空间// 计数int* count = (int*)malloc(sizeof(int) * (max - min + 1));memset(count, 0, sizeof(int)*(max-min+1));for (int i = 0; i < n; i++){count[a[i] - min]++;}//排序int range = (max - min + 1);int j = 0;for (int i = 0; i < range; i++){while (count[i]--){a[j++] = i + min;}}
}

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

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

相关文章

【C++】动态内存管理new和delete

文章目录 一、C的内存管理方式二、new和delete的用法1.操作内置类型2.操作自定义内置类型 三、new和delete的底层实现1.operator new和operator delete函数2.new和delete的实现原理 四、定位new表达式五、malloc/free和new/delete的区别 一、C的内存管理方式 之前在C语言的动态…

kafka(四)消息类型

一、同步消息 1、生产者 同步发送的意思就是&#xff0c;一条消息发送之后&#xff0c;会阻塞当前线程&#xff0c;直至返回 ack。 由于 send 方法返回的是一个 Future 对象&#xff0c;根据 Futrue 对象的特点&#xff0c;我们也可以实现同 步发送的效果&#xff0c;只需在调…

【数据结构】计数排序等排序

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &#x1f4e2;本文由 JohnKi 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f4e2;未来很长&#…

C 语言实例 - 查找数组中最大的元素值

查找数组中最大的元素值。 实例 1 #include <stdio.h>int main() {int array[10] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};int loop, largest;largest array[0];for(loop 1; loop < 10; loop) {if( largest < array[loop] ) largest array[loop];}printf("最大…

Ubuntu系统中创建桌面快捷方式和添加Favorites

一. Ubuntu系统中创建软件的桌面快捷方式 Ubuntu桌面创建某个软件的桌面快捷方式&#xff0c;一个直观的方法。 方法1. 在图像界面下&#xff0c;一层一层地打开文件目录软件快捷方式/usr/share/applications/ 方法2. 或者在终端运行$ nautilus /usr/share/applications/ …

Django靓号管理系统:实现注销功能和重构视图

1. 重构项目结构 首先,我们需要重构项目结构,以更好地组织代码: 在​​web​​目录下创建一个新的​​views​​目录。在​​views​​目录中创建一个新文件​​account.py​​。删除原来的​​views.py​​文件。这样的结构更有利于代码的模块化和维护。 2. 更新 ​​url…

springcloud-config git配置源加载(部署公钥问题)

使用gitUrl作为配置源 gitee 或者github 中有类似于发布密钥的功能&#xff0c;允许通过私钥只读访问指定的仓库&#xff0c;文档中说的是 限制了git的操作为pull 和 clone。生成私钥的方式文档连接在此 https://gitee.com/help/articles/4181#article-header0 spring config只…

简过网:不懂就要问,什么叫考事业单位编制?

不懂就要问&#xff0c;什么叫考事业单位编制&#xff1f;考事业编就是纳入编制的事业单位招聘考试&#xff0c;本质上是还是一种招聘考试&#xff0c;由于是“铁饭碗”&#xff0c;福利好&#xff0c;待遇高&#xff0c;所以对于事业单位的考试一直受人关注。 ​ 一、什么是事…

深度分析 Apache Hudi:大数据实时处理的利器

什么是 Apache Hudi&#xff1f; Apache Hudi&#xff08;Hadoop Upsert Delete and Incremental&#xff09;是一个开源的数据湖存储框架&#xff0c;旨在在大规模数据集上提供高效的增量数据处理和实时数据更新能力。Hudi 由 Uber 开发&#xff0c;并于 2019 年捐赠给 Apach…

精准校准:深入解析scikit-learn中的StandardScaler

精准校准&#xff1a;深入解析scikit-learn中的StandardScaler 在机器学习中&#xff0c;特征缩放是一个至关重要的预处理步骤&#xff0c;它能够显著影响模型的性能。scikit-learn提供了一个强大的工具——StandardScaler&#xff0c;用于将数据标准化到单位方差和零均值。本…

MQ - RabbitMQ、SpringAMQP --学习笔记

什么是MQ&#xff1f; MQ 是消息队列&#xff08;Message Queue&#xff09;的缩写&#xff0c;它是一种应用程序间异步通信的技术。消息队列允许应用程序或服务间通过发送消息来交换数据&#xff0c;而不是直接调用对方&#xff0c;从而实现解耦、异步处理和负载均衡等目的。…

零成本打造精品宣传册

​随着互联网的发展&#xff0c;企业和个人对宣传册的需求日益增长&#xff0c;然而&#xff0c;高质量的宣传册制作往往需要不菲的成本。那么&#xff0c;如何零成本打造精品宣传册呢&#xff1f; 一、明确定位和目标群体 在制作宣传册之前&#xff0c;首先要明确其定位和目标…

qt pro文件常用配置

概述 记录一下常用的项目pro文件的一些常用配置 常用配置 QT core gui concurrent#添加concurrent并行处理模块 CONFIG windeployqt#打包部署&#xff0c;项目->构建步骤->Make参数 添加windeployqt&#xff0c;编译自动打包greaterThan(QT_MAJOR_VERSION, 4):…

Kafka入门到精通(三)-Kafka

Kafka简介 Kafka是由Apache软件基金会开发的一个开源流处理平台&#xff0c;由Scala和Java编写。Kafka是一种高吞吐量的分布式发布订阅消息系统&#xff0c;它可以处理消费者在网站中的所有动作流数据。 这种动作&#xff08;网页浏览&#xff0c;搜索和其他用户的行动&#xf…

强化学习-3深度学习基础

文章目录 1 强化学习与深度学习的关系2 线性回归3 梯度下降4 逻辑回归5 全连接网络6 更高级的神经网络6.1 卷积神经网络6.2 循环神经网络6.3 transformer 将深度学习和强化学习结合起来&#xff0c;利用深度学习网络强大的拟合能力通过将状态、动作等作为输入&#xff0c;来估计…

JeecgBoot新建模块

引言 jeecg-boot设置了demo, system等默认模块。在二次开发中&#xff0c;常常需要进行模块扩展。比如新增一个订单模块或支付模块。如何准确的新增模块&#xff0c;在此文进行记录。 步骤 新建模块 在项目点击右键&#xff0c;新建模块。 如下图。 注意&#xff1a;报名需…

鸿蒙NEXT开发知识:工具常用命令—ohpm config

设置ohpm用户级配置项。 命令格式 ohpm config set <key> <value> ohpm config get <key> ohpm config delete <key> ohpm config list 说明 配置文件中信息以键值对<key> <value>形式存在。 功能描述 ohpm 从命令行和 .ohpmrc 文件中…

Linux命令----wc,uniq,sort的用法

1.wc的用法&#xff1a;wc 命令用于计算文件中的行数、单词数和字节数。 常用选项 -l&#xff1a;只显示行数-w&#xff1a;只显示单词数-c&#xff1a;只显示字节数-m&#xff1a;只显示字符数&#xff08;与 -c 类似&#xff0c;但处理多字节字符&#xff09;-L&#xff1a…

day22--77. 组合+216.组合总和III+17.电话号码的字母组合

一、77. 组合 题目链接&#xff1a;https://leetcode.cn/problems/combinations/ 文章讲解&#xff1a;https://programmercarl.com/0077.%E7%BB%84%E5%90%88.html 视频讲解&#xff1a;https://www.bilibili.com/video/BV1ti4y1L7cv 1.1 初见思路 组合问题用回溯学会使用剪…

SpringBoot:SpringBoot中调用失败如何重试

一、引言 在实际的应用中&#xff0c;我们经常需要调用第三方API来获取数据或执行某些操作。然而&#xff0c;由于网络不稳定、第三方服务异常等原因&#xff0c;API调用可能会失败。为了提高系统的稳定性和可靠性&#xff0c;我们通常会考虑实现重试机制。 Spring Retry为Spri…