归并排序-排序算法

前言

如果一个数组的左右区间都有序,我们可以使用一种方法(归并),使这个数组变得有序。

如下图:

过程也很简单,分别取左右区间中的最小元素,再把其中较小的元素放到临时数组中,例如第一次1和2被取出,1 被放到临时数组;第二次3和2被取出,2 被放到临时数组。重复此操作就能得到有序的临时数组,最后把临时数组拷贝到原数组中就好了。

这就是归并的思想,目前先依照上面过程写出归并方法的代码。注意不是归并排序的代码

#include <iostream>
using namespace std;void mergeAdd0(int arr[], int left, int right,int *temp) //函数参数传入临时数组
{int mid = (left + right) / 2 ; //区间的中间位置,[left,mid]为左区间,[mid+1,right]为右区间int i = left;		//指向左区间最小元素的位置int j = mid + 1 ;	//指向右区间最小元素的位置int k = 0;			//临时数组的下标while (i <= mid && j <= right) //这个循环是取出元素的过程{if (arr[i] < arr[j]){temp[k++] = arr[i++];}else{temp[k++] = arr[j++];}}//因为有一个区间的元素必定会先被取完,下面两个循环是将另一个区间的元素拿到临时数组while (i <= mid){temp[k++] = arr[i++];}while (j <= right){temp[k++] = arr[j++];}//将temp数组拷贝到原数组memcpy(arr + left, temp, sizeof(int) * (right - left + 1 ));}
int main(void)
{int arr[] = { 1 , 3, 5 ,7 ,2 ,4 ,6 ,8 };int len = sizeof(arr) / sizeof(arr[0]);int* temp = new int[len]; //和原数组大小一样的临时数组mergeAdd0(arr, 0, len - 1,temp);for (int i = 0; i < len; i++){cout << arr[i] << " ";}return 0;
}

看完了归并方法,有些人会问,你这个归并方法并不能适用于一般情况,一般数组都是无序的,哪里是你那样的数组:左半边有序,右半边也有序。

也是,下面请先看看归并排序的过程吧(也就是处理一般情况)。

具体步骤

接下来讲的就是排序本身的具体步骤了,对于下面待排序的数组

——170 189 187 186 169 173 162 170 168——

先以中间为界,均分为A、B两组(如果是奇数个,允许两组的个数相差一个)

A——170 189 187 186 169——

B——173 162 170 168——

如果A、B两组数据有序的话,那么就可以通过上面的归并方法让数组有序,可是此时两个数组都无序,此时可以使用分治法继续对A、B两组进行均分,以B组为例,可以分为B1、B2组如下:

B1——173 162——

B2——170 168——

均分后依旧无序,继续利用分治法细分,以B1组为例,可分为如下两组

B11——173——

B12——162——

数组细分到一个元素后,这时候就可以使用之前的归并法借助一个临时数组将B1组有序化!B2数组同理。

B1——162 173——

B2——168 170——

依次类推,B1、B2组有序后,可归并成有序的B组,A组同理。

A——169 170 186 187 189——

B——162 168 170 173——

最后将A、B两组通过归并法合并得到了有序的数组。

——162 168 169 170 170 173 186 187 189——

思路

上面这个过程,按我的理解是:首先归并方法可以使一个左区间有序、右区间有序的数组有序,那左区间怎么有序呢?

恭喜你,学会抢答了。那就是左区间的左区间有序并且左区间的右区间有序(使用归并方法),右区间同理。那左区间的左区间如何有序呢?……直到细分到区间内只有一个元素时,可以保证这个区间有序,从而得到一个个有序区间,最终使数组有序。

这个过程正如排序的名称归并,先递归,使大问题变成小问题,再合并,依次解决问题。

就如上过程结合归并方法可以得到以下代码:

//归并排序
void mergeSort(int arr[], int left, int right, int* temp)
{if (left < right) //区间大于1个数,就要分而治之{int mid = (left + right) / 2;mergeSort(arr, left, mid, temp);  mergeSort(arr, mid+1, right, temp);  mergeAdd(arr, left, right, temp); }
}

归并排序时间复杂度:nlog_{2}^{n} 

全部代码以及测试图

#include <iostream>
#include <time.h>
using namespace std;//归并方法
void mergeAdd(int arr[], int left, int right,int *temp)
{int mid = (left + right) / 2 ; //区间的中间位置,[left,mid]为左区间,[mid+1,right]为右区间int i = left;		//指向左区间最小元素的位置int j = mid + 1 ;	//指向右区间最小元素的位置int k = 0;			//临时数组的下标while (i <= mid && j <= right){if (arr[i] < arr[j]){temp[k++] = arr[i++];}else{temp[k++] = arr[j++];}}while (i <= mid){temp[k++] = arr[i++];}while (j <= right){temp[k++] = arr[j++];}//将temp数组拷贝到原数组memcpy(arr + left, temp, sizeof(int) * (right - left + 1 ));}//归并排序
void mergeSort(int arr[], int left, int right, int* temp)
{if (left < right) //区间大于1个数,就要分而治之{int mid = (left + right) / 2;mergeSort(arr, left, mid, temp);  mergeSort(arr, mid+1, right, temp);  mergeAdd(arr, left, right, temp); }
}
int main(void)
{int arr[] = { 170 ,189,187 ,186 ,169 ,173 ,162 ,170 ,168 };int len = sizeof(arr) / sizeof(arr[0]);int* temp = new int[len]; //和原数组大小一样的临时数组mergeSort(arr, 0, len - 1, temp);for (int i = 0; i < len; i++){cout << arr[i] << " ";}return 0;
}

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

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

相关文章

Fluids —— Volume VOP

P&#xff0c;当前体素位置&#xff1b;density&#xff0c;此场的值&#xff1b;ix, iy, iz&#xff0c;体素索引&#xff08;0 ~ res-1&#xff09;&#xff1b;resx, resy, resz&#xff0c;当前volume的精度&#xff1b;center&#xff0c;当前volume的中心点&#xff1b;o…

AI-数学-高中-3.二次函数的根的分布问题的解题方法

原作者学习视频&#xff1a;二次】3二次函数根分布问题&#xff08;中档&#xff09;_哔哩哔哩_bilibili 一、伟达定理&#xff08;根与0比较的二次函数&#xff09; 示例&#xff1a; 二、画图法&#xff1a; 1.开口方向的确定&#xff0c;有的示例可能存在向上、下两种情况…

OpenAI ChatGPT-4开发笔记2024-01:开发环境

ChatGPT发展一日千里。工具、函数少则数日&#xff0c;多则数月就加入了Deprecated行列不再如预期般工作。元旦闲来无事&#xff0c;用最新的ChatGPT重写一下各种开发场景&#xff0c;全部实测通过。 开发环境&#xff1a; 电脑&#xff1a;两台笔记本&#xff1a;HP和MacBoo…

试用统信服务器操作系统UOS 20

作者&#xff1a;田逸&#xff08;formyz&#xff09; 试用统信Linux操作系统UOS&#xff0c;想了解一下用已有的Linux经验能否轻松驾驭它。以便在某些场景下&#xff0c;可以多一种选择。本次试验在Proxmox VE 8&#xff08;以下简称PVE 8&#xff09;平台下进行&#xff0c;采…

使用Pipeline和ColumnTransformer提升机器学习代码质量

机器学习项目中最冗长的步骤通常是数据清洗和预处理&#xff0c;Scikit-learn库中的Pipeline和 and ColumnTransformer通过一次封装替代逐步运行transformation步骤&#xff0c;从而减少冗余代码量。 1. Pipeline vs. ColumnTransformer 训练模型前&#xff0c;需要将数据集分…

Linux下配置静态ip地址

问题&#xff1a;虚拟机重启后ip地址动态更新&#xff0c;导致连shell十分麻烦 解决&#xff1a; 1. 进入配置文件 vi /etc/sysconfig/network-scripts/ifcfg-ens33 2.1 修改配置 BOOTPROTOstatic ONBOOTyes2.2 新增配置 #ip地址(自定义) IPADDR192.168.149.131 #子网掩码 …

解决问题:PyCharm / IDEA / JetBrains IDEs中 Github Copilot 插件无法使用对话/Chat功能

在Pycharm里装了Github Copilot 插件&#xff0c;但发现只能进行代码补全&#xff0c;没法像ChatGPT一样聊天&#xff0c;CSDN上搜了半天居然没人提出这个问题&#xff0c;于是在Copilot的Github主页上到处寻找答案。 发现这个功能目前还在内测阶段&#xff0c;如果想要使用的…

机器学习-线性回归实践

目标&#xff1a;使用Sklearn、numpy模块实现展现数据预处理、线性拟合、得到拟合模型&#xff0c;展现预测值与目标值&#xff0c;展现梯度下降&#xff1b; 一、导入模块 import numpy as np np.set_printoptions(precision2) from sklearn.linear_model import LinearRegr…

服务器迁移上云

一、服务器迁移上云 1、服务器迁移概念&#xff1a; 服务器迁移一般来说是将物理服务器从一个地点&#xff08;物理机房&#xff09;移动到另一个地点&#xff0c;或将数据从一台服务器移动到另一台服务器的过程。 物理服务器迁移场景&#xff1a; ● 机房搬迁&#xff1a;…

MySQL语法及IDEA使用MySQL大全

在项目中我们时常需要写SQL语句&#xff0c;或简单的使用注解直接开发&#xff0c;或使用XML进行动态SQL之类的相对困难的SQL&#xff0c;并在IDEA中操控我们的SQL&#xff0c;但网上大都图方便或者觉得太简单了&#xff0c;完全没一个涵盖两个方面的讲解。 单表&#xff1a; …

【上海】买套二手房需要多少钱?

上次我们看了苏州的二手房&#xff0c;这次我们一起来看下上海的二手房价格如何。 数据来源 数据来自贝壳二手房&#xff0c;每个区最多获取了3千条房源信息&#xff0c;数据共计4万条左右 对数据感兴趣的朋友&#xff0c;公众号后台发送上海二手房获取数据文件 各区房源单价…

安科瑞电气防火限流式保护器与电动汽车充电桩的搭配使用——安科瑞 顾烊宇

摘要&#xff1a;随着电动汽车行业的不断发展&#xff0c;电动汽车充电设施的使用会变得越来越频繁和广泛。根据中汽协数据显示&#xff0c;2022年上半年&#xff0c;我国新能源汽车产销分别完成266.1万辆和260万辆,同比均增长1.2倍,市场渗透率达21.6%。因此&#xff0c;电动汽…