归并排序

编译环境:gcc4.4.3

#include <stdio.h>

#define MAX 10

void prtarry(int* sum, int n);

//p, q, r均为数组下标
void merge(int *A, int p, int q, int r)
{
    printf("p=%d q=%d r=%d ", p, q, r);

    int i, j, k;
    int n1 = q - p + 1;
    int n2 = r - q;

    int L[MAX], R[MAX];

    for (i = 0; i < n1; i++)
        L[i] = A[p + i];
    for (j = 0; j < n2; j++)
        R[j] = A[q + j + 1];

    /*
     * 哨兵牌
     *L[n1] = 99999;
     *R[n2] = 99999;
     */

    i = 0;
    j = 0;

    for (k = p; k <= r; k++)
    {
        //如果其中一侧的元素复制完了,那么剩下的另一侧元素无需比较,直接复制即可
        //这样做是必须的,因为一侧元素复制完后,它的指针指向的元素就是一个未知数(访问越界)
        //另一种方法是使用哨兵牌,在每一侧末尾放置一个无限大的数。
        if (i >= n1)
        {
            A[k] = R[j++];
            continue;
        }
        else if (j >= n2)
        {
            A[k] = L[i++];
            continue;
        }

        if (L[i] <= R[j])
        {
            A[k] = L[i];
            i++;
        }
        else
        {
            A[k] = R[j];
            j++;
        }
    }

    prtarry(A, r+1);
}

void merge_sort(int *A, int p, int r)
{
    int q;
    if (p < r)
    {
        //q = (p + r) / 2;              //p + r有可能会溢出
        //q = p/2 + r/2;                //两次除法会导致精度成倍降低,导致计算结果错误。例如5/2+3/2=3, (5+3)/2=4
        q = ((p & r) + ((p ^ r) >> 1)); //原理是?
        merge_sort(A, p, q);
        merge_sort(A, q+1, r);
        merge(A, p, q, r);
    }
}

void prtarry(int* sum, int n)
{
    int i;
    printf("array: ");
    for(i=0; i<n; i++)
    {
        printf("%2d ", sum[i]);
    }
    printf("\n");
}

int main(int argc, const char *argv[])
{
    int sum[MAX] = {5,7,8,2,4,6,9,0,1,3};

    prtarry(sum, MAX);
    merge_sort(sum, 0, MAX-1);
    prtarry(sum, MAX);

    return 0;
}
posted @ 2013-02-05 13:38  TonyKong  阅读(256)  评论(0编辑  收藏  举报