复习数据结构:排序算法(四)——归并排序

基本思想:基于分治法,即把待排序的数组序列,分为若干个子序列,对每个子序列排序,然后再把所有有序的子序列合并为一个整体有序的序列。分析可知,如果拿任何一个元素作为子序列,那么所有子序列就已经是有序的,而归并排序的关键就在于如何合并,也就是“归并”。

归并排序是外排序,稳定排序,时间复杂度是O(nlogn).

详细说归并排序的过程:1个元素的表总是有序的。所以对n个元素的待排序列,每个元素可看成1个有序子表。对子表两两合并生成n/2个子表,所得子表除最后一个子表长度可能为1 外,其余子表长度均为2。再进行两两合并,直到生成n 个元素按关键码有序的表。

代码如下:

非递归实现:(经过调试,该程序有bug,后续修正!)

#include<iostream>
using namespace std; 

void Merge(int* r, int* rf, int i, int m, int n)
{
	int j, k;
	for(j = m+1, k = i; i <= m && j <= n; k++)  // i记录第一个子序列标记,j记录第二个子序列标记,k记录合并后序列标记
	{
		if(r[j] < r[i])  //  存入较小者
			rf[k] = r[j++];
		else
			rf[k] = r[i++];
	}
	while(i <= m)  // 如果不等长,就会出现这种情况
		rf[k++] = r[i++];
	while(j <= n)
		rf[k++] = r[j++]; 

	for(int ii = 0; ii < n+1; ii++)
		cout<<rf[ii]<<' ';
	cout<<endl;
}

void MergeSort(int* r, int* rf, int length)
{
	int len = 1;
	int* q = r;
	//int* tmp;
	while(len < length)
	{
		int s = len;
		len = 2*s; // 等长的两个子序列,长度相同
		int i = 0;
		bool flag = true;
		while(i + len <= length)  // 等长的两个子序列合并
		{
			cout<<"等长"<<i<<'-'<<i+s-1<<'-'<<i+len-1<<endl;
			Merge(q, rf, i, i+s-1, i+len-1);  // 注意起始位置的标记
			i += len;  // 下一次合并的起始
			flag = false;
		}
		if(i + s <= length)  // 不等长两个子序列合并
		{
			cout<<"不等长"<<i<<'-'<<i+s-1<<'-'<< length-1<<endl;
			Merge(q, rf, i, i+s-1, length-1);  // 注意最后的结束标记位置
		}

		cout<<"flag="<<flag<<endl;
		if(!flag)
			swap(q, rf);  // 交换指针,该次合并的结果作为下次合并的起始
	}
}

int main()
{
	int a[10] = {11,1,5,7,2,4,9,6,10};  // ,9,6,10,8
	int b[10];
	MergeSort(a, b, 9); 

	for(int i = 0; i< 9; i++)
		cout<<b[i]<<' ';
	cout<<endl; 

	return 0; 

}

递归实现:

void MSort(ElemType *r, ElemType *rf,int s, int t)
{
    ElemType *rf2;
    if(s==t) r[s] = rf[s];
    else
    {
        int m=(s+t)/2;          /*平分*p 表*/
        MSort(r, rf2, s, m);        /*递归地将p[s…m]归并为有序的p2[s…m]*/
        MSort(r, rf2, m+1, t);      /*递归地将p[m+1…t]归并为有序的p2[m+1…t]*/
        Merge(rf2, rf, s, m,t);   /*将p2[s…m]和p2[m+1…t]归并到p1[s…t]*/
    }
}
void MergeSort_recursive(ElemType *r, ElemType *rf, int n)
{   /*对顺序表*p 作归并排序*/
    MSort(r, rf,0, n-1);
}  

参考:

http://blog.csdn.net/xiazdong/article/details/8462393

http://blog.csdn.net/hguisu/article/details/7776068

http://blog.csdn.net/jetjetlinuxsystem/article/details/6589093

时间: 2024-10-01 02:54:21

复习数据结构:排序算法(四)——归并排序的相关文章

python数据结构与算法 34 归并排序

归并排序 在提高排序算法性能的方法中,有一类叫做分而治之.我们先研究其中第一种叫做归并排序.归并排序使用递归的方法,不停地把列表一分为二.如果列表是空或只有一个元素,那么就是排好序的(递归基点),如果列表有超过1个的元素,那么切分列表并对两个子列表递归使用归并排序.一旦这两个列表排序完成,称为"归并"的基本操作开始执行.归并是把两个有序列表合并成一个新的有序列表的过程.图10是我们熟悉的列表样例分解过程,图11是归并的过程. 图10  切分过程 图11  归并过程 以下是mergeSo

排序算法系列——归并排序

记录学习点滴,菜鸟成长记 归并排序的英文叫做Merge-Sort,要想明白归并排序算法,还要从“递归”的概念谈起. 1.递归 一般来讲,人在做决策行事的时候是往往是从已知出发,比如,我又要举个不恰当的例子了→_→: 看到漂亮姑娘→喜欢人家→追→女朋友→老婆 但是人家施瓦辛格不是这么想的,人家从小就立志当总统: 要当总统←先当州长←竞选州长要有钱←那得找个有钱妹子←妹子都喜欢明星←身材好能当明星←健身 递归,就像一个人对自己的发展有清晰的规划和坚定的信心一样,他知道每一步会有怎么样的结果,他需要仅

常用排序算法之——归并排序

归并排序的原理: 如果数组的元素个数大于1,则: 将数组平均分为两部分: 左边的数组归并排序:递归 右边的数组归并排序:递归 将两个各自有序的数组合并,需要一个额外的辅助数组,暂时保存合并结果:返回 否则,数组元素个数为1时,已经有序:直接返回. 稳定排序.时间复杂度在最坏.最好.平均情况下都为O(N lgN),空间复杂度为O(N). 代码: 1 #include <iostream> 2 using namespace std; 3 4 template<typename T>

Java常见排序算法之归并排序

在学习算法的过程中,我们难免会接触很多和排序相关的算法.总而言之,对于任何编程人员来说,基本的排序算法是必须要掌握的. 从今天开始,我们将要进行基本的排序算法的讲解.Are you ready?Let‘s go~~~ 1.排序算法的基本概念的讲解 时间复杂度:需要排序的的关键字的比较次数和相应的移动的次数. 空间复杂度:分析需要多少辅助的内存. 稳定性:如果记录两个关键字的A和B它们的值相等,经过排序后它们相对的位置没有发生交换,那么我们称这个排序算法是稳定的. 否则我们称这个排序算法是不稳定的

黑马程序员——数据结构排序算法总结

-----------android培训.java培训.java学习型技术博客.期待与您交流!------------ 下面是几个网上常见的总结图: 有些不同之处:集中在希尔排序的时间复杂度.快速归并的空间复杂度上 个人总结口诀: 选择N方-->选择排序的最好最坏平均都N方 插入冒泡最好N-->插入冒泡的最好是N,其他是N方 归并堆n乘logN-->归并希尔堆的最好最坏平均都是n乘logN 快速最坏N方-->快速排序的最坏是N方,其他是n乘logN 快速选择希尔堆不稳定-->

排序算法四:交换排序之冒泡排序

排序算法四:交换排序之冒泡排序 声明:引用请注明出处http://blog.csdn.net/lg1259156776/ 引言 在我的博文<"主宰世界"的10种算法短评>中给出的首个算法就是高效的排序算法.本文将对排序算法做一个全面的梳理,从最简单的"冒泡"到高效的堆排序等. 系列博文的前三篇讲述了插入排序的三种不同类型,本文讲述第二大类的排序算法:交换排序,包括冒泡排序和快速排序. 排序相关的的基本概念 排序:将一组杂乱无章的数据按一定的规律顺次排列起

数据结构排序算法Java实现

闲的无聊又拿起了大学的数据结构的书看起来 <数据结构(c语言版)>严蔚敏 吴伟民编著. 里面有几个排序算法,感觉挺好玩的,就想着写出来玩玩. package test.sort; /** * @Title: TODO * @Description: TODO * @author: * @date: 2014-8-10 上午11:20:43 * */ public class quickSort { private static int datas[] = {23,42,12,45,56,63,

数据结构与算法复习(一) 排序算法(I)

这篇文章将会介绍最常见的排序算法(使用 JavaScript 语言实现) PS:这里我会尽量使用语言无关的语法去写,大家不要太在意语言,重要的是算法的实现思路 1.冒泡排序 将数组分为有序区(左边)和无序区(右边) 每次从无序区的最后一个元素开始,一直向前冒泡到无序区的第一个位置,使其变成有序 function swap(A, i, j) { if (i === j) return [A[i], A[j]] = [A[j], A[i]] } function bubbleSort(A) { fo

数据结构复习之排序算法的总结回顾

根据排序过程中借助的主要操作,我们将内排序分为四类: 插入排序类 直接插入排序 希尔排序 选择排序类 简单选择排序 堆排序 交换排序类 冒泡排序 快速排序 归并排序类 归并排序 从算法的简单性来看,我们将7种算法分为两类: 简单算法:冒泡排序.简单选择排序.直接插入排序 改进算法:希尔排序.堆排序.归并排序.快速排序 对7中算法的各种指标进行对比: 平均情况看:显然最后三种算法要胜过希尔算法,并远远超过前3种简单算法. 最好情况看:反而冒泡和直接插入排序要更胜一筹,也就是说,如果待排序序列总是基

图解排序算法(四)之归并排序

基本思想 归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之). 分而治之 可以看到这种结构很像一棵完全二叉树,本文的归并排序我们采用递归去实现(也可采用迭代的方式去实现).分阶段可以理解为就是递归拆分子序列的过程,递归深度为log2n. 合并相邻有序子序列 再来看看治阶段