合并排序(归并排序)

 

1 合并排序采用的是 分治策略

    a 分解:将原问题分解成一系列子问题

    b 解决:递归的解决各个子问题,若问题足够小,则直接求解

    c 合并:将子问题的结果合并成原问题的解

2 将n个元素分成 各含n/2个元素的子序列(重复执行分解动作,直到子程序元素足够小)

3 单个元素被视为 已排好序的

4 为做合并 需要引入辅助操作 

5 合并算法的算法复杂度为 nlgn(低为2)

注意:实现时需要考虑起始下标为 0 或者 为 1 的情况,

   两种方法均可实现(原理相同),但下标的不同直接导致分解方式的不同,

   遇到问题时可在关键位置加入 '打印关键值' 来调试程序

 

void Merge(int array[], int start, int middle, int end) //合并操作的辅助函数

{

    int n1= middle-start; //计算数组大小

    int n2= end-middle;



    int *left = new int[n1]; //动态分配内存

    int *right = new int[n2];



    for(int i=0; i<n1; ++i)  //为已排好序的两组元素 分别赋值到 新的数组

    {

        left[i] = array[start+i]; //从start开始

    }

    for (int j=0; j<n2; ++j)

    {

        right[j] = array[middle+j];  //从middle开始

    }



    int i=0, j=0;

    for(int key=start; key<end; ++key)  

    {

        if (i<n1 && left[i] <= right[j])     //从已排好序的两个数组中分别抽取数据,进行比较

        {

            array[key] = left[i++];            //插入到最初的数组里,更新下标

        }

        else if ( j<n2 && right[j] <= left[i])

        {

            array[key] = right[j++];

        }

        else if (i==n1 && j<n2)        //考虑left数组为空 但right数组依然还有数据时

        {

            array[key] = right[j++];

        }

        else if (j==n2 && i<n1)        //考虑right数组为空 但left数组依然还有数据时

        {

            array[key] = left[i++];

        }

    }



    delete [] left;        //释放内存

    delete [] right;

}

//第一次调用该函数,start的下标为从零开始,

//也可以不考虑下标从1开始,但实现方式(主要是分解条件及分解方法 注意下标)需要做相应修改

void MergeSort(int array[], int start, int end) 

{

    if(start+1 < end)   //分解条件 子问题只有两个元素 例如 start=0,end=1 结束分解

    {

        int middle = (start+end)/2; //分解方式 子问题为原问题的一半

        //for (int i=0; i<10; ++i)

        //{

        //    cout << array[i] << " ";

        //}

        //cout << endl;

        MergeSort(array,start,middle);  //分解方法 middle在此作为边界条件(其功能与end相同充当哨兵位,不能访问该下标) 

        MergeSort(array,middle,end);    //middle在此作为起始下标

        Merge(array,start,middle,end);  //例如 merge(8,9,10) 实际进行排序的只有 array[8] 与 array[9]

        //for (int i=0; i<10; ++i)

        //{

        //    cout << array[i] << " ";

        //}

        //cout << endl;

    }

}

void main()

{

    //判断是否有内存泄露,需要加头文件#include <crtdbg.h>

    _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF|_CRTDBG_LEAK_CHECK_DF); 



    int Array[10] = {4, 1, 3, 2, 16, 9, 10, 14, 8, 7};



    MergeSort(Array, 0, 10);



    for (int i=0; i<10; ++i)

    {

        cout << Array[i] << endl;

    }



    system("pause");

}

 

你可能感兴趣的:(归并排序)