C++版 归并排序
在原作者基础上加入注释
原作者:https://www.cnblogs.com/agui521/p/6918229.html
归并排序:归并排序(英语:Merge sort,或mergesort),是创建在归并操作上的一种有效的排序算法,效率为O(n log n)。1945年由约翰·冯·诺伊曼首次提出。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用,且各层分治递归可以同时进行。
归并排序的核心思想是将两个有序的数列合并成一个大的有序的序列。通过递归,层层合并,即为归并。

如图,从下到上,每一步都需要将两个已经有序的子数组合并成一个大的有序数组,如下是实现合并的具体代码,请读者细细体会
void merge(int arr[],int l,int mid,int r)
{
int aux[r-l+1];//开辟一个新的数组,将原数组映射进去
for(int m=l;m<=r;m++)
{
aux[m-l]=arr[m];
} int i=l,j=mid+1;//i和j分别指向两个子数组开头部分 for(int k=l;k<=r;k++)
{
//分四种情况判断:
//i>mid 把大于mid的数据并入;j>r 把i-mid的数据并入;
//aux[i-l]<aux[j-l],把小的数据即aux[i-l]并入,同理aux[i-l]>=aux[j-l]
if(i>mid)
{
arr[k]=aux[j-l];
j++;
}
else if(j>r)
{
arr[k]=aux[i-l];
i++;
}
else if(aux[i-l]<aux[j-l])
{
arr[k]=aux[i-l];
i++;
}
else
{
arr[k]=aux[j-l];
j++;
}
}
}
上图代码已经完成了归并中的“并”这一部分,归并归并,有并必有归,如下实现“归”的部分

1 void merge_sort(int arr[],int l,int r)
2 {
3 if(l >=r)
4 return ;
5 int mid=(l+r)/2;
6 merge_sort(arr,l,mid); //这个函数的递归为了获取 l和mid 的值
7 merge_sort(arr,mid+1,r); //这两个递归主要为了获取 r 的值 为下面的 merge函数提供实参
8 merge(arr,l,mid,r);
9 }

由于上图中的l,r不方便使用者调用,于是我们创建一个方便自己调用的my_merge_sort函数
1 void my_merge_sort(int arr[],int n)
2 {
3 merge_sort(arr,0,n-1);
4 }
以上我们便实现了归并排序中的归和并,归并排序是利用二分法实现的排序算法,时间复杂度为nlogn,是一种比较快速的排序算法。如下是笔者自己写的归并排序的全部代码,

1 #include <iostream>
2 using namespace std;
3
4
5 void merge(int arr[],int l,int mid,int r)
6 {
7 int aux[r-l+1];//开辟一个新的数组,将原数组映射进去
8 for(int m=l;m<=r;m++)
9 {
10 aux[m-l]=arr[m];
11 }
12
13 int i=l,j=mid+1;//i和j分别指向两个子数组开头部分
14
15 for(int k=l;k<=r;k++)
16 {
17 if(i>mid)
18 {
19 arr[k]=aux[j-l];
20 j++;
21 }
22 else if(j>r)
23 {
24 arr[k]=aux[i-l];
25 i++;
26 }
27 else if(aux[i-l]<aux[j-l])
28 {
29 arr[k]=aux[i-l];
30 i++;
31 }
32 else
33 {
34 arr[k]=aux[j-l];
35 j++;
36 }
37 }
38 }
39 //递归的使用归并排序,对arr[l....r]排序
40 void merge_sort(int arr[],int l,int r)
41 {
42 if(l >=r)
43 return ;
44 int mid=(l+r)/2;
45 merge_sort(arr,l,mid);
46 merge_sort(arr,mid+1,r);
47 merge(arr,l,mid,r);
48 }
49
50 void my_merge_sort(int arr[],int n)
51 {
52 merge_sort(arr,0,n-1);
53 }
54
55 int main()
56 {
57 int a[6];
58 for(int i=0;i<6;i++)
59 {
60 cin>>a[i];
61 }
62 my_merge_sort(a,6);
63 for(int i=0;i<6;i++)
64 {
65 cout<<a[i]<<" ";
66 }
67 return 0;
68 }

上面实现的归并排序是自顶向下的,我们可以以另外一种方向来实现归并,改递归为迭代。如下实现

1 #include <iostream>
2 #include <math.h>
3 using namespace std;
4
5 void merge(int arr[],int l,int mid,int r)
6 {
7 int aux[r-l+1];//开辟一个新的数组,将原数组映射进去
8 for(int m=l;m<=r;m++)
9 {
10 aux[m-l]=arr[m];
11 }
12
13 int i=l,j=mid+1;//i和j分别指向两个子数组开头部分
14
15 for(int k=l;k<=r;k++)
16 {
17 if(i>mid)
18 {
19 arr[k]=aux[j-l];
20 j++;
21 }
22 else if(j>r)
23 {
24 arr[k]=aux[i-l];
25 i++;
26 }
27 else if(aux[i-l]<aux[j-l])
28 {
29 arr[k]=aux[i-l];
30 i++;
31 }
32 else
33 {
34 arr[k]=aux[j-l];
35 j++;
36 }
37 }
38 }
39
40 void mergesort(int arr[],int n)
41 {
42 for(int sz=1;sz<=n;sz+=sz)
43 {
44 for(int i=0;i+sz<n;i+=sz+sz)//i+sz防止越界 i+=sz+sz 相当于 i+=(sz+sz) 先2个2个排序,再4个4个排序,再8个8个排序 45 {//对arr[i...sz-1]和arr[i+sz.....i+2*sz-1]进行排序
46 merge(arr,i,i+sz-1,min(i+sz+sz-1,n-1)); //min函数防止越界
47 }
48 }
49
50 }
51
52 int main()
53 {
54 int a[5];
55 for(int i=0;i<5;i++)
56 {
57 cin>>a[i];
58 }
59 mergesort(a,5);
60 for(int i=0;i<5;i++)
61 {
62 cout<<a[i]<<" ";
63 }
64 return 0;
65 }

C++版 归并排序的更多相关文章
- javascript实现非递归--归并排序
另一道面试题是实现归并排序,当然,本人很不喜欢递归法,因为递归一般都是没有迭代法好.所以首选都是用迭代法,但是迭代法确实是难做啊,至底而上的思想不好把握. 这是我的实现代码 /* * * 非递归版归并 ...
- 算法与数据结构(十五) 归并排序(Swift 3.0版)
上篇博客我们主要聊了堆排序的相关内容,本篇博客,我们就来聊一下归并排序的相关内容.归并排序主要用了分治法的思想,在归并排序中,将我们需要排序的数组进行拆分,将其拆分的足够小.当拆分的数组中只有一个元素 ...
- 算法导论(第三版)Exercises2.3(归并排序、二分查找、计算集合中是否有和为X的2个元素)
2.3-1: 3 9 26 38 41 49 52 59 3 26 41 52 9 38 49 57 3 41 52 26 38 57 9 49 3 41 52 26 38 ...
- 归并排序—Java版
一开始做算法的时候,感觉递归算法很绕,所以我就在阅读别人代码的基础上,对代码每一步都添加自己的注解,方便我以后的学习. public class MergeSort { /** * 归并排序 * @p ...
- C#版 - LeetCode 148. Sort List 解题报告(归并排序小结)
leetcode 148. Sort List 提交网址: https://leetcode.com/problems/sort-list/ Total Accepted: 68702 Total ...
- 结合《剑指offer(第二版)》面试题51来谈谈归并排序
一.题目大意 给定一个数组A,对于数组A中的两个数字,如果排在前面的一个数字大于(必须大于,等于不算)后面的数字,则这两个数字组成一个逆序对.要求输出数组A中的逆序对的总数.例如,对于数组{7,5,6 ...
- 算法分析中最常用的几种排序算法(插入排序、希尔排序、冒泡排序、选择排序、快速排序,归并排序)C 语言版
每次开始动手写算法,都是先把插入排序,冒泡排序写一遍,十次有九次是重复的,所以这次下定决心,将所有常规的排序算法写了一遍,以便日后熟悉. 以下代码总用一个main函数和一个自定义的CommonFunc ...
- 数据结构之排序技术:快速排序、归并排序、堆排序(C++版)
快速排序 #include <iostream> using namespace std; void swap(int num[], int i, int j) { int temp = ...
- C++_归并排序(纯C版)
#include <iostream> #include <stdlib.h> using namespace std; int compared(const void *ke ...
随机推荐
- 【线性代数】7-1:线性变换思想(The Idea of a Linear Transformation)
title: [线性代数]7-1:线性变换思想(The Idea of a Linear Transformation) categories: Mathematic Linear Algebra k ...
- 畅通工程续(HDU 1874)(简单最短路)
某省自从实行了很多年的畅通工程计划后,终于修建了很多路.不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多.这让行人很困扰. 现在 ...
- hive的两种使用方式
hive的两种使用方式 1,hive shell的方式 启动命令: bin/hive 2.beeline客户端方式 首先在一个机器上启动hive thrift服务 bin/hiveserver2 在其 ...
- js 选择文本
怎么用js脚本,选中文本呢? // 获取selection对象 var selection = window.getSelection(); // 清空selection对象 selection.re ...
- P2119 魔法阵
原题链接 https://www.luogu.org/problemnew/show/P2119 YY同学今天上午给我们讲了这个题目,我觉得她的思路很好,特此写这篇博客整理一下. 50分:暴力枚举 ...
- Ubuntu 14.04 tar 打包系统安装到新机器
制作Ubuntu14.04 的u启动盘,重启电脑进入要克隆的系统,打包整个根目录 su cd / tar -cvpzf /media/cdrom/backup.tar.gz / --exclude=/ ...
- shell 统计行数,单词个数,字符个数
如果我们想知道1.txt中有多少行,多少个单词,多少个字符.我们可以使用wc命令.选项与参数-l:今列出行-w:今列出多少字(英文单词)-m:多少字符[zhang@localhost ~]$ cat ...
- mapreduce 倒序 排序 最简单 易上手
对于mapreduce倒序只需要建立一个类,然后继承WritableComparator 在重写 Compare函数最后在main里调用一下,就可以实现倒序排序: 代码: public static ...
- MySQL二进制包安装
mysql的安装有多种方法,这里就介绍一下二进制包安装. [root@node1 ~]# tar xvf mysql-5.7.27-linux-glibc2.12-x86_64.tar [root@n ...
- CF1217B
CF1217B 题意: 有一个有 $ x $ 个头的龙,你有 $ n $ 种方案,每种方案中包含你可以砍掉的头 $ d_i $ 和龙会生长的头 $ h_i $ 找到一种方案,使得操作数最少. 解法: ...