算法导论(4)归并排序

#pragma once
#include<limits>

/*合并两个已经排序好的子序列
两个已经排序好的子序列为src[startIndex]-src[middleIndex];src[middleIndex+1]-src[endIndex]
*/
template<class T>
void Merge(T *src, int startIndex, int middleIndex, int endIndex)
{
	int n1 = middleIndex - startIndex + 1;
	int n2 = endIndex - middleIndex;

	//使L[n1],R[n2]成为新的数组
	T *L = new T[n1 + 1];
	T *R = new T[n2 + 1];
	for (int i = 0; i < n1; i++) {
		L[i] = src[startIndex + i];
	}
	for (int i = 0; i < n2; i++) {
		R[i] = src[middleIndex + i + 1];
	}

	//哨兵牌,设置为该类型的最大值
	L[n1] = numeric_limits<T>::max();
	R[n2] = numeric_limits<T>::max();

	int i = 0, j = 0;
	for (int k = startIndex; k <= endIndex; k++) {
		if (L[i] <= R[j]) {
			src[k] = L[i];
			i++;
		}else{
			src[k] = R[j];
			j++;
		}
	}

	//删除动态分配的数组
	delete[] L;
	delete[] R;
}
/*
归并排序
*/
template<class T>
void MergeSort(T *src, int startIndex, int endIndex)
{
	if (startIndex < endIndex) {
		//这一部分相当于分治
		int midIndex = (startIndex + endIndex) / 2;
		MergeSort(src, startIndex, midIndex);
		MergeSort(src, midIndex + 1, endIndex);

		//这一部分相当于合并
		Merge(src, startIndex, midIndex, endIndex);
	}
}
时间: 2024-10-26 22:50:40

算法导论(4)归并排序的相关文章

【算法导论】归并排序

递归与分治 许多有用的算法在结构上是递归的:为了解决一个给定的问题,算法一次或多次递归地调用其自身以解决紧密相关的若干子问题.这些算法典型地遵循分治法的思想:将原问题分解为几个规模较小但类似于原问题的子问题,递归地求解这些子问题,然后再合并这些子问题的解来建立原问题的解. 分治模式在每层递归时都有三个步骤: 分解原问题为若干子问题,这些子问题是原问题的规模较小的实例. 解决这些子问题,递归地求解各子问题.然而,若子问题的规模足够小,则直接求解. 合并这些子问题的解成原问题的解. 归并排序 归并排

算法导论:归并排序

归并排序是建立在归并操作上的一种有效的排序算法.该算法是采用分治法(Divide and Conquer)的一个非常典型的应用. 归并操作(merge),指的是将两个已经排序的序列合并成一个序列的操作. 对两个排序数组合并成一个有序数组,这个很简单 public int[] merge(int[] A,int[] B){ int aLen = A.length; int bLen = B.length; int cLen = aLen + bLen; int[] C = new int[cLen

算法导论学习笔记(2)-归并排序

今天学习了算法导论上的归并排序算法,并且完成了在纸上写出伪代码,以前就学过归并但是理解的不够透彻,以 前还一直困惑:为什么明明归并排序比快排的时间复杂度更稳定,为什么库函数不用归并而用快排,现在知道原因了,因为归并排序必须开额外的空间,而且空间开销还比较大,下面介绍算法: 首先,归并排序用到了分治的思想,把大数据分成若干个小数据,然后再分别对小数据进行处理,最后把小数据 合并成大数据. 其次,归并排序用到了一个最重要的特点,就是把两组已经排序的数据合并成一组有序数据,并且该过程的时间复 杂度为O

算法导论之插入排序和归并排序

一.创建我们的测试工程 因为我们只理解相应算法,没有什么用户图形,也就用不到UI了,在这儿使用Xcode创建一个基于Mac开发的控制台工程即可,整个工程很简单,一个main函数一个排序类,如下所示. 在Sort类中我们写了关于排序的一些类方法,然后在main函数中进行调用. 二.插入排序 插入排序顾名思义,就是把无序的元素插入到有序的元素当中.<算法导论>中举了一个特为形象的例子,插入排序就如同你在打扑克时摸牌一样,手里的牌是有序的,而你刚摸得牌是是随机的,需要你插入到已经排好序的扑克牌中,这

《算法导论》读书笔记之排序算法—Merge Sort 归并排序算法

自从打ACM以来也算是用归并排序了好久,现在就写一篇博客来介绍一下这个算法吧 :) 图片来自维基百科,显示了完整的归并排序过程.例如数组{38, 27, 43, 3, 9, 82, 10}. 在算法导论讲分治算法一章的时候提到了归并排序.首先,归并排序是一个分治算法. 归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表, 即把待排序序列分为若干个有序的子序列,再把有序的子序列合并为整体有序序列. merg() 函数是用来合并两个已有序的数组.  是整个算法的关键. 那么归并

算法导论 (一)归并排序实现 c++

#include <iostream> using namespace std; void Merge_Sort(int *a,int p,int q ,int r)//归并 { int i,j,k; int n1=q-p+1; int n2=r-q; int *le=NULL; int *ri=NULL; le = new int [n1]; ri = new int[n2]; for(i=0;i<n1;i++) { le[i]=a[p+i]; } for(j=0;j<n2;j+

算法导论学习之插入排序+合并排序

最近准备花时间把算法导论详细的看一遍,强化一下算法和数据结构的基础,将一些总结性的东西写到博客上去. 一.插入排序 算法思想:如果一个数组A,从A[1–n-1]都是有序的,然后我们将A[n]插入到A[1–n-1]的某个合适的位置上去那么就可以保证A[1–n]都是有序的.这就是插入排序的思想:具体实现的时候我们将数组的第一个元素看出有序,然后从第二个元素开始按照上面的步骤进行插入操作,直到插入最后一个元素,然后整个数组都是有序的了. 时间复杂度分析:代码中有两重for循环,很容易看出时间复杂度是n

算法导论_第二章(1)

年前的时候去逛书店,久仰算法导论这本书的大名看见后也就买了下来.回家看了一段时间,发现看书的进度真的是极慢,书里的课后题很多,那些不会的问题也是通过网上搜别人的答案才得以解决的.所以,我就想把我看这本书的心得连带课后的解答分享给大家.同时也是给我坚持把算法导论这本书看完的一个动力 ^_^ 因为本书的第一章相当于一个导论就直接跳过了,那么,从第二章开始! 第二章主要介绍了插入排序和归并排序: 所谓的插入排序就像是一局扑克刚开始时的摸牌阶段,你对手中的扑克所做的整理排序一样.开始时,我们的左手为空并

算法导论6:排序小结和最值取法 2016.1.6

今天想做测试各个排序算法运行时间比较的程序,来对这几天学的排序算法小结一下.所以我先生成了1000000个1~150之间的随机数存到文件里.然后做了一个测试运行时间的程序.想看一下结构.但是结果效果并不太好.实践中,自己做的qsort函数和mergesort函数并没有理想中的那么快. 结果是这样:(可能并不准确,但却是是运行结果) 库函数快速排序:0.139000 seconds自制快速排序:0.375000 seconds归并排序:0.358000 seconds堆排序:0.525000 se

算法导论2:几个习题 2016.1.2

一.在归并排序中对小数组采用插入排序(放在上一篇里了): 二.冒泡排序 冒泡排序效率几乎是所有排序里最低的,但却很流行,就是因为它的变成复杂度也是最低的.大多数时候,效率还不及插入排序,其实冒泡排序.插入排序.选择排序基本上效果是差不多的(这个效果不是功能..功能上讲肯定差不多啊都是排序),只是过程略有区别.既然写到这里,就自己总结一下三者吧. 1.插入排序——摸扑克牌的过程 假定前一个是有序的,把第二个插进它应当在的位置,那么前两个就是有序的了,把第三个插进它应当在的位置,那么前三个就是有序的