zoukankan      html  css  js  c++  java
  • 合并排序(归并排序)

    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");
    }
  • 相关阅读:
    (转载)C#如何在任务管理器中不显示指定的窗体
    Windows上配置Mask R-CNN及运行示例demo.ipynb
    如何选择普通索引和唯一索引?
    relay(跳板机)搭建
    javascript 9x9乘法口诀表
    canvas画布爆炸
    Chrome Network Timing 解释
    JavaScript中对数组的定义
    jquery each 和 map 区别
    css 兼容性转换网站
  • 原文地址:https://www.cnblogs.com/sevenPP/p/3614904.html
Copyright © 2011-2022 走看看