• 归并排序


    引子:

    看了归并排序,觉得这才真正像个算法,插入,选择,冒泡简直特么的就像是暴力猜解密码一样的弱。

    测试了100000个随机数字的排序,比上述3个算法的运行时间少了近100倍的数量级。


    算法思想:

    归并排序的主要思路是分治,可以大概参考二分查找的思路,并且也是递归的方式。

    首先按数组长度将数组切成左右两半,先将左边排序,再将右边排序,再将两边的合并起来,并且在合并的过程中排序,需要在栈中建立一个新的同样大小的数组用于缓存。

    在每次拆分以后,有一个起点索引 nStart,一个中点索引 nMid,一个终点索引 nEnd,这时需要再次将nStart到nMid拆分成三个节点,直到nStart大于或等于nEnd,退出递归。

    然后进行排序,递归的逻辑如下:

    void MergeSort(int* ua, int nStart, int nEnd)
    {
    	if(nStart >= nEnd)
    	{
    		return;
    	}
    	int nMid = nStart + (nEnd - nStart) / 2;
    
    	MergeSort(ua, nStart, nMid);
    	MergeSort(ua, nMid+1, nEnd);
    	Merge(ua, nStart, nMid, nEnd);
    }


    排序的过程需要借助一个临时数组用来合并,比较左边和右边数据的大小来选择性地插入数据,如果左边的全都插完了,就开始插右边的。但是判断左右是否插完的逻辑要先于插入数据的逻辑,代码如下:

    void Merge(int* ua, int nStart, int nMid, int nEnd)
    {
    	int a[N];
    	int i = nStart;
    	int j = nMid + 1;
    
    	for (int k = nStart; k <= nEnd; k++)
    	{
    		a[k] = ua[k];
    	}
    
    	for (int k = nStart; k <= nEnd; k++)
    	{
    		if(i > nMid)
    		{
    			ua[k] = a[j++];
    		}
    		else if(j > nEnd)
    		{
    			ua[k] = a[i++];
    		}
    		else if( a[j] < a[i])
    		{
    			ua[k] = a[j++];
    		}
    		else
    		{
    			ua[k] = a[i++];
    		}
    	}
    }


    整体的代码量不大,但是需要想清楚整个递归过程和递归退出的条件。

    假设一共10个随机数,从小到大排序:

    第一步是按索引拆分,

    先拆成0,1,2,3,4 和 5,6,7,8,9

    再将0,1,2,3,4 拆分成 0,1,2 和 3,4

    再将0,1,2,拆分成 0,1 和 2

    0 和 1 不可以再拆了,于是开始对0,1进行排序 

    再对2进行排序,因为2只有一个数,所以直接跳过了。

    完成后再将0,1 与 2 合到一起进行排序,

    然后再对3,4进行排序。

    再将0,1,2,3,4一起进行排序

    最后将0,2,3,4,5,6,7,8,9一起排序


    因为每次排序其实只是对两个数进行比较然后插入数组,所以速度是很快的。

    测试代码如下:

    #include "stdafx.h"
    #include "windows.h"
    #include "time.h"
    
    const int N = 10;
    int O = 0;
    
    int* GenRandom()
    {
    	srand( (unsigned)time( NULL ) );
    
    	int* a = new int[N];
    	for (int i = 0; i < N; i++)
    	{
    
    		a[i] = rand() ;
    	}
    	return a;
    }
    
    SYSTEMTIME StartTime = {0};
    FILETIME StartFileTime = {0};
    SYSTEMTIME EndTime= {0};
    FILETIME SEndFileTime= {0};
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	int* a = GenRandom();
    	GetLocalTime(&StartTime);
    	printf("timeBefore %d:%d:%d 
    ", StartTime.wMinute, StartTime.wSecond, StartTime.wMilliseconds);
    
    	MergeSort(a,0,N-1);
    
    	GetLocalTime(&EndTime);
    	printf("timeAfter %d:%d:%d 
    ", EndTime.wMinute, EndTime.wSecond, EndTime.wMilliseconds);
    	printf("times %d 
    ", O);
    	return 0;
    }




  • 相关阅读:
    ln 命令使用
    python 调用浏览器方法
    Git新手必备常用命令
    Spring 整合 Hibernate 入门
    看看什么是Guice
    maven 详解,其它这几篇文章也不错
    shell编程中date用法(转)
    通过scp实现vps控制没有外网IP的localhost
    centos6.6安装python2.7
    Cygwin配置
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3202905.html
Copyright © 2020-2023  润新知