[数据结构]归并排序

news/2025/2/25 16:08:54

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

归并排序

简述

归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
其对数组进行排序时的基本操作在于两个有序序列进行合并操作。其代码部分在后面给出。

而进行整体数组排序时,可先将
n个元素看作n个有序序列,对其两两进行合并,于是结果成为floor(n/2)个有序序列,再将其进行两两合并。直到最终合并成为一个整体有序序列。

后面给出的算法包含两个版本。一个是递归方法,另一个是非递归方法。其中递归方法是分治法的典型应用。

代码实例


#include<iostream>
using namespace std;
void dispList(int raw[], int n){
	//打印数组
	//from 1 to n not 0 to n
	for (int i = 1; i <= n; i++) cout << raw[i] << ' ';
}

void mergeSort(int raw[], int n){
	//merge with no recursion非递归方法
	int *temp = new int[n + 1]; //由于合并操作的辅助空间需要对等的长度
	for (int i = 1; i < n; i = i * 2){//两两归并,直到归并的长度大于序列长度跳出
		int right_a, right_b, left_a, left_b;	//每次比较[left_a...left_b-1]; [right_a...right_b-1]
		int cursor = 1;//记录相对位置,每进行一趟归并将其重新置为1
		for (left_a = 1; left_a <= n - i; left_a = right_b){
			left_b = right_a = left_a + i;
			right_b = right_a + i;
			if (right_b>n + 1) right_b = n + 1;//如果甩下一个尾巴不够i长度,那么直接将right_b置n+1;
			//如下格式是经典的合并三段while语句
			while (left_a < left_b && right_a<right_b)
				temp[cursor++] = (raw[left_a]<raw[right_a]) ? (raw[left_a++]) : (raw[right_a++]);
			while (left_a < left_b)
				temp[cursor++] = raw[left_a++];
			while (right_a < right_b)
				temp[cursor++] = raw[right_a++];
		}
		//将辅助空间写入原始序列.
		while ((--cursor) != 0)
			raw[cursor] = temp[cursor];
	}
	delete [] temp;
}
//以下给出递归方法,注意体会分治思想。
void merge_joint(int raw[], int temp[], int start, int middle, int end){
    //每次meger raw[start...middle-1] and raw[middle...end]
    int cursor_l = start, cursor_r = middle;
    int cursor = start;
    //同样,三段经典while合并语句
    while (cursor_l < middle && cursor_r <= end)
        temp[cursor++] = (raw[cursor_l] < raw[cursor_r]) ? raw[cursor_l++] : raw[cursor_r++];
    while (cursor_l < middle)
        temp[cursor++] = raw[cursor_l++];
    while (cursor_r <= end)
        temp[cursor++] = raw[cursor_r++];
    while ((--cursor) >= start) 
        raw[cursor] = temp[cursor];//合并好后写入原始序列
}
void merge_R(int raw[], int temp[], int n, int start, int end){
    if (start == end) return;
    else{
        int mid = (start + end) / 2;
        //先合并左面,再合并右边,最后合并整体
        merge_R(raw, temp, n, start, mid);    
        merge_R(raw, temp, n, mid + 1, end);
        merge_joint(raw, temp, start, mid + 1, end);
    }
}
void mergeSortRe(int raw[], int n){
    //最后调用归并排序
    int *temp = new int[n + 1];
    merge_R(raw, temp, n, 1, n);//需要传入辅助空间
    delete [] temp;
}

void main(){
    int a[9] = { 0, 3, 4, 8, 6, 7, 23, 21, 18 };
    mergeSortRe(a, 8);
    dispList(a, 8);

}

复杂度分析

一趟归并调用对长度为 2h-1 子序列的两两合并操作。其次数约为 n/(2h), 一直到最后,需要进行的排序趟数为:

结合两种操作,最后其时间复杂度为O(nlogn).
由于合并操作需要等长辅助空间,所以空间复杂度为
O(n)

总结

复杂度为O(nlogn)
需要等长辅助空间

相比于快排和堆排序,它是一种稳定排序

归并排序在实际应用中较少作为内部排序。递归方式调用实用性差。



转载于:https://my.oschina.net/o0Kira0o/blog/277913


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

相关文章

rec删除xposed_刷机,twrp,安装xposed

首先明白几个名词&#xff1a;recovery模式&#xff0c;类似于pc端的PE系统&#xff0c;每个手机都有自带的rec&#xff0c;但不好用&#xff0c;最好自己刷一个&#xff0c;现在市面最好用的是twrpfastboot模式&#xff0c;比recovery更底层&#xff0c;进入fastboot可以刷第三…

matlab中nntool,matlab nntool

输入【1.00 0.34 0.63 0.5 0.64 0.49 0.520.19 0.18 0.06 1 0.14 0.04 0.180.94 0.00 0.14 0.5 0.19 0.17 1.000.13 …

web前端学习(三十三)——JavaScript变量、数据类型的相关设置

1.JS变量 与代数一样&#xff0c;JavaScript 变量可用于存放值&#xff08;比如 x5&#xff09;和表达式&#xff08;比如 zxy&#xff09;。变量是用于存储信息的"容器"。 变量可以使用短名称&#xff08;比如 x 和 y&#xff09;&#xff0c;也可以使用描述性更好的…

rsa 公 填充模式的_RSA中pkcs1的填充方法具体是什么?

展开全部1)RSA_PKCS1_PADDING 填充模式&#xff0c;最常用的模式要求:输入 必须32313133353236313431303231363533e4b893e5b19e31333262353433 比 RSA 钥模长(modulus) 短至少11个字节, 也就是 RSA_size(rsa) – 11如果输入的明文过长&#xff0c;必须切割&#xff0c; 然后填充…

iMatrix平台中子标签(grid:subGrid)的参数说明

2019独角兽企业重金招聘Python工程师标准>>> 子表标签(grid:subGrid) 参数说明&#xff1a; 1. 子表标签必须和列表标签&#xff08;参照3.列表标签&#xff09;组合使用&#xff0c;首先在【系统元数据管理】【表单管理】【数据表管理】中录入数据表&#xff0…

php预约成功的短信,去驾校报名,然后发个短信,交警发的,说预约注册成功,然后干嘛...

意思是&#xff1a;可以网上预约考试了。报名后体检照相录&#xff0c;车申请建档&#xff0c;车管所审批后才会给你短信。这个时间大致要十天左右。扩展资料&#xff1a;驾驶机动车需要一定的驾驶技能&#xff0c;缺少这种技能的如果随意驾驶机动车&#xff0c;就有可能发生交…

关于ListView的setEmptyView没效果的问题

使用listView或者gridView时&#xff0c;当列表为空时。有时须要显示一个特殊的empty view来提示用户&#xff0c;普通情况下&#xff0c;假设你是继承ListActivity。仅仅要 TextView tv new TextView(this); tv.setText("this is a empty view") setEmptyView(tv…

web前端学习(三十四)——JavaScript对象、函数及作用域(全局变量、局部变量)的相关设置

1.JS对象 JavaScript 对象是拥有属性和方法的数据。在JavaScript中&#xff0c;几乎所有的事物都是对象。&#xff08;这和Java一样啊&#xff0c;万物皆对象&#xff01;&#xff01;&#xff01;&#xff09; 可以使用字符来定义和创建 JavaScript 对象&#xff0c;定义 Java…