• 排序之归并排序


    归并是将两个有序的序列归并为一个有序序列,在这里,“两个有序序列”是指同一个序列中含有两部分“有序”的子序列,我们要做的就是把这两个有序的子序列“合并”,使其整体成为一个有序的序列。为了做到这一点,我们可以创建一个和原序列大小相同的空间(这里用数组表示),然后通过两个指针同时扫描原序列中的两个有序的子序列,将较小的数据放到我们新创建的数组中,最后得到的是一个有序的序列,然后将这个有序的序列拷贝的原序列中,这样就完成了原序列的归并。归并算法描述如下:

    1、merge(array,left,mid,right)//这里array[left,mid],array[mid+1,right]是有序的子序列

    2、  创建temArray,空间大小为right-left+1;

    3、  定义临时变量i=left,j=mid+1,k=0;

    4、  while(i<=mid && j<=right){

    5、    if(array[i] < array[j]){

    6、      temArray[k++]=array[i++];

    7、    }else{

    8、      temArray[k++]=array[j++];

    9、    }

    10、  }

    11、  while(i<=mid){ temArray[k++]=array[i++]; }

    12、  while(j<=right){ temArray[k++]=array[j++]; }

    13、  for(i=0;i<k;i++){ array[left+i]=temArray[i]; }//将归并好的序列赋给原序列

    那么,我们怎么划分"有序子序列"呢?鉴于递归的简洁性,我们可以用递归方法划分:对原序列进行二分,一直进行下去,直到得到的子序列是单个值的时候,单个值的子序列默认是有序的,然后再进行反向归并,如下图所示:

    利用递归方法进行归并排序的完整程序如下:

    public class Test{
        public static void main(String[] args)throws InterruptedException{
            int arr[]={1,4,23,0,4,5,34,23,4354,23,12,13};
            printArray(arr);
            merge_sort(arr,0,arr.length-1);
            printArray(arr);
        }
        
        static void merge_sort(int[] array,int left,int right){
            if(left<right){
                int mid=left+(right-left)/2;
                merge_sort(array,left,mid);
                merge_sort(array,mid+1,right);
                merge(array,left,mid,right);
            }
        }
        static void merge(int[] array,int left,int mid,int right){
            int[] temp=new int[right-left+1];
            int i=left,j=mid+1,k=0;//注意,这里的左右两边的子序列的下脚标与上面的调用一定要一致!尤其是右边子序列下脚标从哪开始从哪结束
            while(i<=mid && j<=right){ //i=left to mid-1;j=mid to right
                if(array[i]<array[j]){
                    temp[k++]=array[i++];
                }else{
                    temp[k++]=array[j++];
                }
            }
            while(i<=mid){
                temp[k++]=array[i++];
            }
            while(j<=right){//j=mid to right
                temp[k++]=array[j++];
            }
            for(i=0;i<k;i++){
                array[left+i]=temp[i];
            }
        }    
        static void printArray(int[] array){
            for(int val:array){
                System.out.print(val+" ");
            }
            System.out.println();
        }
    }

    归并排序算法性质:

    1、归并排序算法的稳定性和归并算法有关,如果归并是稳定的,则归并排序也是稳定的。

    2、归并排序算法的时间复杂度是O(nlgn),空间复杂度是O(n)。

    3、归并排序算法的比较次数和序列的初始排序无关。

    以上是个人总结,有误之处,请各位大侠指出

  • 相关阅读:
    VS调试技巧
    Git 分支
    WPF:如何高速更新Model中的属性
    Redis-4.0.11集群配置
    大压力下Redis参数调整要点
    统计UPD丢包工具
    查看Redis集群所有节点内存工具
    Redis集群命令行部署工具
    查看Redis集群主从对应关系工具
    Redis集群master选举时长测试
  • 原文地址:https://www.cnblogs.com/codeMedita/p/7412568.html
Copyright © 2020-2023  润新知