排序(二):归并排序

news/2024/5/17 17:42:51 标签: 经典排序算法, 归并排序

目录

1.什么是归并排序

2. 和选择排序,冒泡排序等的暴力排序的区别在哪里,为什么快?

3.  代码实现归并排序


了解其他常用算法点这里 >> https://blog.csdn.net/GD_ONE/article/details/104061907


归并排序是分治法思想的实例,学习完归并排序后会更加理解分治法思想和递归思想。

  1. 什么是归并排序
  2. 和选择排序,冒泡排序的区别在哪里,为什么它要比以上两种排序快呢?
  3. 我们要怎么实现归并排序?

本文将主要解决以上三个问题。

1.什么是归并排序

归并排序的主要思想是:

    1). 归0    

      将无序的数列分为两个部分,对于每个部分,在继续划分为更小的两部分,直到每个部分都有序,即分解为单个数据,因为仅有一个数一定是有序的。

    2). 合并

      把每次分开的两部分再合并到一起。合并是归并排序的核心。

2. 和选择排序,冒泡排序等的暴力排序的区别在哪里,为什么快?

    选择排序和冒泡排序直接对原数列进行遍历比较,要比较n+(n-1)+(n-2)...+1次,时间复杂度为o(n^2)

    归并排序采用了分治法思想,将待排序的数列分解为两个更小的数列,分解数列的时间复杂度为o(log2n),每一次分解都需要将两个有序的数列合并在一起,合并两个有序数列的时间复杂度是o(n)所以总的时间复杂度是 o(nlog2n)。

3.  代码实现归并排序

先看下图, 图来自https://www.cnblogs.com/onepixel/p/7674659.html

动态图

 
 

   首先解决分的问题,需要将数列分为两个部分, 在将每个部分再次分为两个部分,直到不可再分。

   我们可以使用递归的方式来实现归并排序,其实分治法的思想几乎就是递归的过程。

对于每一个序列,每次都按左右两部分划分,所以 int  mid = l+r>>1;

然后对 (l, mid) 和 (mid + 1, r) 两部分再次递归划分。当l == r  时不再继续划分。

( 另: l+r >>1 是位运算, 相当于 (l+r)/ 2

代码:   

int mergesort(int a[], int l, int r){
    if(l==r) return;
    int mid = l+r>>1;
    mergesort(a, l, mid);
    mergesort(a, mid+1, r);
}

  分完之后就剩下合并了

  上面说到  将两个有序的序列合并为一个, 那么怎么合并呢, 首先我们当然需要一个额外的数组去存储这个合并后的序列

  然后比较将两个有序的序列的每一个数据,按照大小关系将数据存入额外数组。

  如 1 3 5  和 2 4 6

  先比较1 2       1 < 2   将1存入, 然后比较2  3   2 < 3 将2存入 以此类推。

   完整代码:

void mergesort(int a[], int l, int r){
	if(l>=r) return;
	int mid = l+r>>1;
	mergesort(a, l, mid);
	mergesort(a, mid+1, r);
	int i,j,k = l;
	for(i = l, j = mid + 1; i <= mid&&j <= r;){
		if(a[i] > a[j]){
			b[k++] = a[j];
			j++;
		}
		else b[k++] = a[i], i++;
	} 
	while(i <= mid) b[k++] = a[i++];
	while(j <= r) b[k++] = a[j++]; 
	for(int ii = l; ii <= r; ii++){
		a[ii] = b[ii];
	}
}

 

 

 


http://www.niftyadmin.cn/n/1465632.html

相关文章

[leetCode]349. 两个数组的交集

博客园:https://www.cnblogs.com/PythonFCG/p/13870851.html 给定两个数组&#xff0c;编写一个函数来计算它们的交集。 示例 1&#xff1a; 输入&#xff1a;nums1 [1,2,2,1], nums2 [2,2] 输出&#xff1a;[2] 示例 2&#xff1a; 输入&#xff1a;nums1 [4,9,5], num…

[leetCode]202. 快乐数

博客园: https://www.cnblogs.com/PythonFCG/p/13870962.html 编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」定义为&#xff1a;对于一个正整数&#xff0c;每一次将该数替换为它每个位置上的数字的平方和&#xff0c;然后重复这个过程直到这个数变为 1&#xff0c;也…

[leetCode]845. 数组中的最长山脉

博客园:https://www.cnblogs.com/PythonFCG/p/13872391.html 原题地址&#xff1a;https://leetcode-cn.com/problems/longest-mountain-in-array 我们把数组 A 中符合下列属性的任意连续子数组 B 称为 “山脉”&#xff1a; B.length > 3 存在 0 < i < B.length - 1…

状态压缩DP_01 :最短Hamilton路径

哈密顿路径的定义是从起始点到结束点不重不漏地经过每个点恰好一次。 那么哈密顿路径的所有情况就是0123..n数列的全排列了。 如果要求出最短路径&#xff0c; 枚举全排列的话时间复杂度就达到了o&#xff08;n*n!&#xff09;级别 这道题的正解是状态压缩DP 那么什么是状态…

[leetCode]212场周赛

博客园&#xff1a;https://www.cnblogs.com/PythonFCG/p/13874794.html 题目一: 5546. 按键持续时间最长的键 链接&#xff1a;https://leetcode-cn.com/problems/slowest-key LeetCode 设计了一款新式键盘&#xff0c;正在测试其可用性。测试人员将会点击一系列键&#xff08…

JAVA基础语法:常用功能符以及循环结构和分支结构

文章目录1.常用功能符注释算术运算符取模运算符自增自减运算符关系运算符逻辑运算符三目运算符2.分支结构if..elseif..else if .. elseswitch - case3.循环结构whiledo..whileforbreakcontinue了解其他JAVA 常用API和算法点这里 >> https://blog.csdn.net/GD_ONE/article…

JAVA基础语法:函数(方法)、类和对象

文章目录函数static修饰符类和对象了解其他JAVA 常用API和算法点这里 >> https://blog.csdn.net/GD_ONE/article/details/104061907 函数 在java中函数也称为方法&#xff0c;是一段具备某种功能的可重用代码块。 一个函数包括这几部分&#xff1a; 函数头 函数头包括函…

[leetCode]144. 二叉树的前序遍历

博客园:https://www.cnblogs.com/PythonFCG/p/13884266.html 题目 链接&#xff1a;https://leetcode-cn.com/problems/binary-tree-preorder-traversal 给定一个二叉树&#xff0c;返回它的 前序 遍历。 示例:输入: [1,null,2,3] 1\2/3 递归 class Solution {public List<…