归并排序

归并排序(Merge sort,台湾译作:合并排序)是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。

归并操作

归并操作(merge),也叫归并算法,指的是将两个已经排序的序列合并成一个序列的操作。归并排序算法依赖归并操作。


 算法描述

归并操作的过程如下:

  1. 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
  2. 设定两个指针,最初位置分别为两个已经排序序列的起始位置
  3. 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
  4. 重复步骤3直到某一指针达到序列尾
  5. 将另一序列剩下的所有元素直接复制到合并序列尾

示例代码


C++语言

//#只完成兩段之間歸併的功能#%
void Merge(int a[], int b[], int low, int mid, int high)
{
    int k = low;
    int begin1 = low;
    int end1 = mid;
    int begin2 = mid + 1;
    int end2 = high;
    while(begin1 <= end1 && begin2 <= end2)
    {
        if(a[begin1] <= a[begin2])
            b[k++] = a[begin1++];
        else
            b[k++] = a[begin2++];
    }
    if(begin1 <= end1)
        for(int q = begin1; q <= end1; q++)
            b[k++] = a[q];
    else
        for(int q = begin2; q <= end2; q++)
            b[k++] = a[q];
}
 
void MergePass(int a[], int b[], int seg, int size)
{
    int seg_start_ind = 0;
    while(seg_start_ind <= size - 2 * seg) //#size - 2 * seg的意思是滿足可兩兩歸併的最低臨界值#%
    {
        Merge(a, b, seg_start_ind, seg_start_ind + seg - 1, seg_start_ind + seg * 2 - 1);
        seg_start_ind += 2 * seg;
    }
    //#如果一段是正好可歸併的數量而另一段則少於正好可歸併的數量#%
    if(seg_start_ind + seg < size)
        Merge(a, b, seg_start_ind, seg_start_ind + seg - 1, size - 1);
    else
        for(int j = seg_start_ind; j < size; j++) //#如果只剩下一段或者更少的數量#%
            b[j] = a[j];
}
 
void MergeSort(int a[], int size)
{
    int* temp = new int[size];
    int seg = 1;
    while(seg < size)
    {
        MergePass(a, temp, seg, size);
        seg += seg;
        MergePass(temp, a, seg, size);
        seg += seg;
    }
}
 
int main()
{
    int a[] = {3, 5, 3, 6, 4, 7, 5, 7, 4}; //#QQ#%
    MergeSort(a, sizeof(a) / sizeof(*a));
    //#輸出#%
    for(int i = 0; i < sizeof(a) / sizeof(*a); i++)
        cout << a[i] << ' ';
    cout << endl;
 
    return 0;
}


示例代码为C语言,输入参数中,需要排序的数组为array[],起始索引为first,终止索引为last。调用完成后,array[]中从first到last处于升序排列。

void merge_sort(int array[], unsigned int first, unsigned int last)
{
        int mid = 0;
        if(first<last)
        {
                /*mid = (first+last)/2;*/ /*注意防止溢出*/
                /*mid = first/2 + last/2;*/
                mid = (first & last) + ((first ^ last) >> 1);
                merge_sort(array, first, mid);
                merge_sort(array, mid+1,last);
                merge(array,first,mid,last);
        }
}

如果不使用递归,而是迭代,则C代码为:

void merge_sort(int *list, int length){
        int i, left_min, left_max, right_min, right_max, next;
        int *tmp = (int*)malloc(sizeof(int) * length);
        if (tmp == NULL){
                fputs("Error: out of memory\n", stderr);
                abort();
        }
        for (i = 1; i < length; i *= 2)
                for (left_min = 0; left_min < length - i; left_min = right_max){ 
                        right_min = left_max = left_min + i;
                        right_max = left_max + i;
                        if (right_max > length)
                                right_max = length;
                        next = 0;
                        while (left_min < left_max && right_min < right_max)
                                tmp[next++] = list[left_min] > list[right_min] ? list[right_min++] : list[left_min++];
                        while (left_min < left_max)
                                list[--right_min] = list[--left_max];
                        while (next > 0)
                                list[--right_min] = tmp[--next];
                }
        free(tmp);
}



posted @ 2012-07-18 18:08  wdliming  阅读(111)  评论(0编辑  收藏  举报