合并排序

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

合并排序描述

        合并排序本质上是将一个无序元素集分割成多个只包含一个元素的集,然后不断的将这些小的集合并,直到一个新的大有序数据集生成。例如:对于一个需要排序的数组A[0...n-1],合并排序把它一分为二:A[0...(n/2)-1]和A[(n/2)...n-1],并对每个子数组递归排序,然后把这两个排好序的子数组合并为一个有序数组。


        算法:

MergeSort(A[i...k])
 //递归调用MergeSort对数组A[i...k]排序
 //输入:一个可排序数组A[i...k]
 //输出:非降序排列的数组A[i...k]

 j<-(k+i-1)/2

 if l < k
     MergeSort(A[i...j])
     MergeSort(A[j+1...k])
     Merge(A[i...j], A[j+1...k])

        对两个有序数组的合并可以通过下面的算法完成:初始状态下,两个指针(数组下标)分别指向两个待合并数组的第一个元数。如果一个数据集没有要合并的元素,那么将另外一个集中要合并的元素全部放到合并的集合中。否则,首先比较两个集合中的首元素,判断哪个元素将要放到合并的集合中,然后将它放置进去,接着根据元素来自的集合移动相应指针的位置(移到指向下一个元素的位置)。


        算法:

Merge(A[i...j], A[j+1...k])
	//将两个有序数组合并成一个有序数组
	//输入:两个有序数组 A[i...j]和 A[j+1...k]
	//输出:非降序排列的数组A[i...k]

	iPos <- i
    jPos <- j+1
    mPos <- 0

	M <- malloc

	while iPos <= j or jPos <= k	
		if iPos > j
			while jPos <= k
				copy(M[mPos], A[jPos])
				jPos++
				mPos++

			continue
		else if jPos > k
			while iPos <= j
				copy(M[mPos], A[iPos])
				iPos++
				mPos++

			continue
		else
			if (A[iPos] < A[jPos])
				copy(M[mPos], A[iPos])
				iPos++
			else
				copy(M[mPos], A[jPos])
				jPos++

			mPos++

	copy(A[i], M[0])

	M <- free


合并排序的实现


// MergeSort.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include "typedef.h"

/*
*函数名:Compare_uint
*参数:pKey1  指向第一个比较元素的地址
*      pKey2  指向第二个比较元素的地址
*功能:比较两个元素的大小
*返回值:1 表示Key1 大于 Key2
*        -1 表示Key1 小于 Key2
*        0 表示Key1 等于 Key2
*作者:AlbertoNo1
*日期:2016-03-15
*/
INT32 Compare_uint(VOID *pKey1, VOID *pKey2)
{
	/*对两个无符号整型数进行比较*/
	if (*((UINT32*)pKey1) > *((UINT32*)pKey2))
	{
		return 1;
	}
	else if (*((UINT32*)pKey1) < *((UINT32*)pKey2))
	{
		return -1;
	}
	else
	{
		return 0;
	}
}

/*
*函数名:Merge
*参数:pData  待合并数组数据的首地址
*      uiElmSize  数据元素所占内存大小(Byte)
*      i 数组的开始下标
*      j 数组的中间位置
*      k 数组的结束下标
*      compare  两个元素的比较函数
*功能:对两个有序数据集进行非降序合并
*返回值:0 成功 -1 失败
*作者:AlbertoNo1
*日期:2016-03-17
*/
INT32 Merge(VOID *pData, UINT32 uiElmSize, INT32 i, INT32 j, INT32 k, INT32 (*compare)(VOID *Key1, VOID *Key2))
{
	INT32 iPos = 0;
	INT32 jPos = 0;
	INT32 mPos = 0;

	CHAR *pucData = NULL;
	CHAR *pucTemp = NULL;

	/*初始化两个有序数据集的开始位置及临时存储区的开始位置*/
	iPos = i;
	jPos = j+1;
	mPos = 0;

	pucData = (CHAR*)pData;

	/*申请用于合并两个有序数据集的存储空间*/
	if (NULL == (pucTemp = (CHAR*)malloc((k-i+1)*uiElmSize)))
	{
		return -1;
	}

	while((iPos <= j) || (jPos <= k))
	{
		if(iPos > j)
		{/*左侧数据集已全部合并完成*/
			while(jPos<=k)
			{
				memcpy(&pucTemp[mPos*uiElmSize], &pucData[jPos*uiElmSize], uiElmSize);
				jPos++;
				mPos++;
			}

			continue;
		}
		else if (jPos > k)
		{/*右侧数据集已全部合并完成*/
			while(iPos <= j)
			{
				memcpy(&pucTemp[mPos*uiElmSize], &pucData[iPos*uiElmSize], uiElmSize);
				iPos++;
				mPos++;
			}

			continue;
		} 
		else
		{/*两个数据集的元素进行比较*/
			if (compare(&pucData[iPos*uiElmSize], &pucData[jPos*uiElmSize]) < 0)
			{
				memcpy(&pucTemp[mPos*uiElmSize], &pucData[iPos*uiElmSize], uiElmSize);
				iPos++;
			} 
			else
			{
				memcpy(&pucTemp[mPos*uiElmSize], &pucData[jPos*uiElmSize], uiElmSize);
				jPos++;
			}

			mPos++;
		}
	}

	memcpy(&pucData[i*uiElmSize], &pucTemp[0], (k-i+1)*uiElmSize);

	free(pucTemp);

	return 0;
}

/*
*函数名:MergeSort
*参数:pData  待合并数组数据的首地址
*      uiElmSize  数据元素所占内存大小(Byte)
*      uiSize 数据的元素个数
*      i 数组的开始下标
*      k 数组的结束下标
*      compare  两个元素的比较函数
*功能:对数组进行合并排序
*返回值:0 成功 -1 失败
*作者:AlbertoNo1
*日期:2016-03-17
*/
INT32 MergeSort(VOID *pData, UINT32 uiSize, UINT32 uiElmSize, INT32 i, INT32 k, INT32 (*compare)(VOID *Key1, VOID *Key2))
{
	INT32 j = 0;  

	if (i < k)
	{
		/*选择划分位置,取数组中间值*/
		j = (k+i-1)/2;

		/*对左侧数据集继续合并排序*/
		if (MergeSort(pData, uiSize, uiElmSize, i, j, compare) < 0)
		{
			return -1;
		}

		/*对右侧数据集继续合并排序*/
		if (MergeSort(pData, uiSize, uiElmSize, j+1, k, compare) < 0)
		{
			return -1;
		}

		/*对数据进行合并*/
		if (Merge(pData, uiElmSize, i, j, k, compare) < 0)
		{
			return -1;
		}
	}

}

int _tmain(int argc, _TCHAR* argv[])
{
	INT32 iRet = 0;
	UINT32 uiLoop = 0;

	//UINT32 auiData[] = {10,15,15,18,20,20,20,36,48,51,51,77,77};
	UINT32 auiData[] = {77,77,51,51,48,36,20,20,20,18,15,15,10};
	//UINT32 auiData[] = {77,15,20,18,51,51,36,10,77,15,20,20,48};
	//UINT32 auiData[] = {77,77};
	//UINT32 auiData[] = {77};

	(VOID)MergeSort(auiData, sizeof(auiData)/sizeof(auiData[0]), sizeof(auiData[0]), 0, ((sizeof(auiData)/sizeof(auiData[0]))-1),Compare_uint);

	printf("Quick Sort Success.\n");
	printf("Result:\n");

	for (uiLoop = 0; uiLoop < sizeof(auiData)/sizeof(auiData[0]); uiLoop++)
	{
		printf("%d  ", auiData[uiLoop]);
	}

	getchar();

	return 0;
}


Java实现合并排序 1 问题描述 给定一组数据,使用合并排序得到这组数据的非降序排列。 2 解决方案 2.1 合并排序原理简介 引用自百度百科: 合并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。 合并排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序... 阅读详情

相关推荐

合并排序

合并排序(Merge Sort)是一种基于分治思想的排序算法,其原理如下:1.将待排序数组分成两个子数组,每个子数组包含大约相等数量的元素。2.递归地对子数组进行排序,直到每个子数组的大小为1。3.将已排序子数组合并成一个新的排序数组,合并过程中按照从小到大的顺序逐个比较两个子数组中的元素,并将较小的元素放入新数组中,直到所有元素都被放入新数组中。4.最终得到一个有序数组。合并排序的时间复杂度是O(nlogn),其中n是待排序数组的长度。它的空间复杂度是O(n)。

weixin_47225948的博客 2328

合并排序归并排序

合并排序,大致思想便是先将数组中的元素拆分成若干小部分,然后再将这些小部分按照顺序进行重新组合,从而实现排序。很明显,这里用到了分治法的思想,即将一个大问题分成若干个相同的小问题,因为问题规模变小了,所以解决问题的难度也随之减小,试想一下,对一个拥有10000个元素的数组进行排序简单还是对一个只拥有1个元素的数组进行排序简单?答案很明显。 对于合并排序,将大问题分成若干小问题是一件很容易的事情,只需要不断递归即可,其中最主要的难点就是将这些小问题解决之后,如何再将这些小问题合并起来,若是处理不好,很可能就导

学习永无止境 1万+

算法重温:排序 —— 合并排序

合并排序算法原理、复杂度及实现(c++、java)

weixin_50553521的博客 7376

算法笔记【8】-合并排序算法

合并排序算法通过采用分治策略和递归思想,实现了高效、稳定的排序功能。本文将深入探讨合并排序算法的原理、实现步骤,并讨论其优缺点。

chen_mp的博客 2264

排序算法-合并排序法(MergeSort)

合并排序法(MergeSort)是针对已排序好的两个或两个以上的数列(或数据文件),通过合并的方式将其组合成一个大的且已排好序的数列(或数据文件)

Hank_W 3039

详解自然合并排序

既然是详解自然合并排序,那就一步一步讲解算法: (‾◡◝) 学习自然合并排序,首先我们要先知道: 自然合并排序合并排序的区别: 合并排序 : 是将两个(或两个以上)有序表合并成一个新的有序表 自然合并排序: 就是在合并排序时,建立子数组段,通过数组已排序的(自然排序,不重新排序子数组段。 下面通过步骤讲解自然合并排序到底是怎样操作的:( ﹁ ﹁ ) ~→ 自然合并排序步骤: 简单的说,自然...

shengshengxiaowang的博客 3514

递归排序(合并排序)

1. 递归排序(合并) 合并排序是分而治之的排序算法。它是一种高效,基于比较的排序算法。 它的工作原理如下: 将列表划分为每次迭代中大约一半大小的子列表,直到每个子列表只有一个元素。 重复合并每个子列表以创建排序列表。它将一直运行,直到我们只有一个排序列表。这将是排序列表。 如下图 2. 代码实现 import java.util.Arrays; public class MergeSor...

我和这个时代的故事 1万+

合并排序算法排序过程_基本算法合并排序

合并排序算法排序过程 每个程序员都需要了解他们的算法和数据结构。 在研究它们时,您需要确保确切了解它的功能,时间和空间的复杂性以及采用这种方式的原因,并且不仅能够对其进行编码,而且能够手动执行。 这就是基本算法的全部意义。 欢迎来到基本算法的第一次安装,今天在这里,我们将介绍合并排序合并排序是用于对大型数据集进行排序的最可靠的一致且性能最佳的排序算法之一,比起快速排序平均而言, 最糟糕的...

编程故事的地方 7753

Python合并排序

Here you will learn about python merge sort algorithm. 在这里,您将了解python合并排序算法。 Merge sort is based on divide and conquer technique. 合并排序基于分而治之。 All we have to do is divide our array into 2 parts or ...

culing2941的博客 1737

合并排序与快速排序

合并排序算法又叫归并排序,是用分治策略实现对n个元素进行排序算法将待排序元素分成大小大致相同的两个子集合,分别对两个子集合进行排序,最终将排好序的子集合合并成所要求的排好序的集合。 合并方法是循环的将两个有序子序列当前的首元素进行比较,较小的元素取出,置入合并序列的左边空置位,直至其中一个子序列的最后一个元素置入合并序列中。最后将另一个子序列的剩余元素按顺序逐个置入合并序列尾部即可完成排序。(二分法) 由于排序问题的计算下界为Ω(nlog n),所以合并排序是一个渐进最优算法 /* input 10 10

weixin_53113130的博客 3503

合并排序Java实现

在计算机科学中,合并排序(通常拼写为mergesort)是一种基于O(n log n)比较的排序算法。大多数实现产生稳定的排序,这意味着实现保留排序输出中相等元素的输入顺序。Mergesort是一种分而治之的算法。划分和征服算法将原始数据划分为较小的数据集来解决问题。 在Mergesort过程中,集合中的对象分为两个集合。要拆分集合,Mergesort将占据集合的中间位置,并将集合拆分为左侧和右...

javaZhong的博客 2136

自然合并排序

自然合并排序算法是对合并排序算法的一种改进。设 a[0:n-1]是无序数组,用一次对数组a的扫描可以找出其中 自然排好序的子数组,然后将相邻的排好序的子数组段两 两合并,继续合并相邻排好序的子数组段,直至将整个数 组排好序。 code: #include <algorithm> #include <iostream> using namespace std; in...

成龙大侠的博客 680

排序算法合并排序

合并排序法 (Merge Sorting) 是外部排序最常使用的排序方法。 主要应用场景是:若数据量太大无法一次完全加载内存, 可使用外部辅助内存来处理排序数据,主要应用在文件排序排序方法: 将欲排序的数据分别存在数个文件大小可加载内存的文件中, 再针对各个文件分别使用“内部排序法” 将文件中的数据排序好写回文件。 再对所有已排序好的文件两两合并, 直到所有文件合并成一个文件后, 则...

shao15232的博客 2371
上一篇: 快速排序
下一篇: 选择排序
AlbertoNo1
博客等级 码龄11年 8粉丝 19原创
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值