归并排序

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");
}

参考资料

上一篇下一篇

猜你喜欢

热点阅读