美文网首页
归并排序

归并排序

作者: jeckHao | 来源:发表于2018-03-29 11:46 被阅读0次

    简介:

    归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(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");
    }
    

    参考资料

    相关文章

      网友评论

          本文标题:归并排序

          本文链接:https://www.haomeiwen.com/subject/kilmcftx.html