归并排序
2018-03-29 本文已影响0人
jeckHao
简介:
归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
基本思想:
将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。
归并过程:
比较a[i]和a[j]的大小,若a[i]≤a[j],则将第一个有序表中的元素a[i]复制到r[k]中,并令i和k分别加上1;否则将第二个有序表中的元素a[j]复制到r[k]中,并令j和k分别加上1,如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到r中从下标k到下标t的单元。
归并排序的算法其实要做两件事:分解,合并。
根据分解的方式不同,实现方法可分为两种:递归法,迭代法。前者比较常用。
用递归实现:
也叫二路归并,先把待排序区间[s,t]以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]。
image.png
代码实现,纯C语言版本:
/********************** 归并排序 **********************/
/**
合并两个数组
@param sources 原数组
@param tempArr 临时数组,用于存储排序后的数组
@param startIndx 第一个数组的开始下标
@param midIndex 第一个数组的结束下标,midIndex+1为第二个数组的开始下标
@param endIndex 第二个数组的结束下标
*/
void Merge(int sources[], int tempArr[], int startIndx, int midIndex, int endIndex) {
int idx1 = startIndx, idx2 = midIndex+1, tempIdx = startIndx; //idx1,idx2为两个数组的开始下标。tempIdx为临时数组开始下标
while (idx1 < midIndex+1 && idx2 < endIndex+1) {
//查找两个数组的最小值
tempArr[tempIdx++] = (sources[idx1] < sources[idx2] ? sources[idx1++] : sources[idx2++]);
}
//将数组1中没加入的值加入临时数组中
while (idx1 < midIndex+1) {
tempArr[tempIdx++] = sources[idx1++];
}
//将数组2中没加入的值加入临时数组中
while (idx2 < endIndex+1) {
tempArr[tempIdx++] = sources[idx2++];
}
//将临时数组中的值复制到原数组中
for (int i=startIndx; i<=endIndex; i++) {
sources[i] = tempArr[i];
}
}
/**
递归-归并排序
@param sources 原数组
@param tempArr 临时数组
@param startIndex 开始位置
@param endIndex 结束位置
*/
void MergeSort_Recursion(int sources[], int tempArr[], int startIndex, int endIndex) {
if (startIndex < endIndex) {
int midIndex = (startIndex + endIndex) / 2;
//递归左边数组
MergeSort_Recursion(sources, tempArr, startIndex, midIndex);
//递归右边数组
MergeSort_Recursion(sources, tempArr, midIndex+1, endIndex);
//合并两个左右数组
Merge(sources, tempArr, startIndex, midIndex, endIndex);
}
}
/********************** 归并排序 **********************/
int main(int argc, const char * argv[]) {
int arr[10] = {1,32,44,32,111,222,1,2,7,4};
int temp[10];
MergeSort_Recursion(arr, temp, 0, 9);
for (int i=0; i<10; i++) {
printf("%d\t",arr[i]);
}
printf("\n");
}