合并排序描述
合并排序本质上是将一个无序元素集分割成多个只包含一个元素的集,然后不断的将这些小的集合并,直到一个新的大有序数据集生成。例如:对于一个需要排序的数组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;
}