• 归并排序


     归并排序(Merging Sort)就是将两个或两个以上的有序表合并成一个有序表的过程。将两个有序表合并成一个有序表的过程称为2-路归并,2-路归并最为简单和常用。下面以2-路归并为例,介绍归并排序算法

    归并排序算法的思想

      假设初始序列含有n个记录,则可看成是n个有序的子序列,每个子序列的长度为1,然后两两归并,得到[n/2]个长度为2或1的有序子序列;再两两归并,……,如此重复,直至得到一个长度为n的有序序列为止。

      2-路归并排序的过程如图所示

     

      2-路归并排序中的核心操作是,将待排序序列中前后相邻的两个有序序列归并为一个有序序列。


    归并排序的两种实现策略

    递归法

    原理如下(假设序列共有n个元素):

    1、将原始序列从中间分为左、右两个子序列,此时序列数为2

    2、将左序列和右序列再分别从中间分为左、右两个子序列,此时序列数为4

    3、重复以上步骤,直到每个子序列都只有一个元素,可认为每一个子序列都是有序的

    4、最后依次进行归并操作,直到序列数变为1

    代码实现

    package com.hxy.sort;
    
    
    import java.util.Arrays;
    
    public class MergeSort1{
    
        public static void main(String[] args) {
            int[] arr= {2,5,7,4,9,3,4,};
            System.out.println("未排序前的顺序");
            System.out.println(Arrays.toString(arr));
            mergeSort(arr,new int[arr.length],0,arr.length-1);
            System.out.println("排序之后的顺序");
            System.out.println(Arrays.toString(arr));
        }
    
        public static void merge(int[] arr,int[] temp, int low , int mid, int high){
           int i = low, j = mid+1;
            int k = 0;
    
            while(i<=mid&&j<=high){
                if(arr[i]<=arr[j]){
                    temp[k]=arr[i];
                    k++;
                    i++;
                }else{
                    temp[k]=arr[j];
                    k++;
                    j++;
                }
            }
            //如果左边有剩余而右边已经添加完 直接把左边剩余的按着顺序添加到临时数组temp中
            while (i<=mid){
                temp[k]=arr[i];
                k++;
                i++;
            }
            //如果右边有剩余而左边已经添加完 直接把右边剩余的按着顺序添加到临时数组temp中
            while (j<=high){
                temp[k]=arr[j];
                k++;
                j++;
            }
    
            //将临时序列中有序的序列赋给原序列
            for(int t = 0; t<k;t++){
                arr[low+t]= temp[t];
            }
    
        }
    
    
        public static void mergeSort(int[] arr, int[] temp ,int low ,int high){
            if(low<high){
                //将序列分为左右两部分
                int mid  = (low+high)/2;
                //将左边的序列进行归并排序
                mergeSort(arr,temp,low,mid);
                //将右边的序列进行归并排序
                mergeSort(arr,temp,mid+1,high);
                //将两段有序的序列合为一段有序的序列
                merge(arr,temp,low,mid,high);
            }
    
        }
    
    }

    迭代法

    原理如下(假设序列共有n个元素):

    1、将序列每相邻两个数进行归并操作,形成ceil(n/2)个序列,排序后每个序列包含两/一个元素

    2、将序列每相邻的两个有序子序列进行归并操作,形成ceil(n/4)个序列,每个序列包含四/三个元素

    3、重复步骤2,直到所有元素排序完毕,即序列数为1个

    void Merge(int*a,int low,int mid,int high)
    
    {
    
        inti=low,j=mid+1,k=0;
    
        int *temp=(int*)malloc((high-low+1)*sizeof(int));
    
        while(i<=mid&&j<=high)
    
            a[i]<=a[j]?(temp[k++]=a[i++]):(temp[k++]=a[j++]);
    
        while(i<=mid)
    
            temp[k++]=a[i++];
    
        while(j<=high)
    
            temp[k++]=a[j++];
    
        memcpy(a+low,temp,(high-low+1)*sizeof(int));
    
        free(temp);
    
    }
    
    void MergeSort(int*a,int n)
    
    {
    
        int length;
    
        for(length=1; length<n; length*=2)
    
        {
    
            int i;
    
            for(i=0; i+2*length-1<=n-1; i+=2*length)
    
                Merge(a,i,i+length-1,i+2*length-1);
    
            if(i+length<=n-1)
    
                 Merge(a,i,i+length-1,n-1);
    
        }
    
    }

    递归和迭代的区别


    递归和迭代都是循环的一种。简单地说,递归是重复调用函数自身实现循环。迭代是函数内某段代码实现循环,而迭代与普通循环的区别是:循环代码中参与运算的变量同时是保存结果的变量,当前保存的结果作为下一次循环计算的初始值。

    递归循环中,遇到满足终止条件的情况时逐层返回来结束。迭代则使用计数器结束循环。当然很多情况都是多种循环混合采用,这要根据具体需求。

    递归与迭代都是基于控制结构:迭代用重复结构,而递归用选择结构。 递归与迭代都涉及重复:迭代显式使用重复结构,而递归通过重复函数调用实现重复。 递归与迭代都涉及终止测试:迭代在循环条件失败时终止,递归在遇到基本情况时终止。 使用计数器控制重复的迭代和递归都逐渐到达终止点:迭代一直修改计数器,直到计数器值使循环条件失败;递归不断产生最初问题的简化副本,直到达到基本情况。迭代和递归过程都可以无限进行:如果循环条件测试永远不变成false,则迭代发生无限循环;如果递归永远无法回推到基本情况,则发生无穷递归。 递归函数是通过调用函数自身来完成任务,而且在每次调用自身时减少任务量。而迭代是循环的一种形式,这种循环不是由用户输入而控制,每次迭代步骤都必须将剩余的任务减少;.

    动图展示.

    归并排序动图

    算法分析

      ①时间复杂度

      当有n个记录时,需进行log2n趟归并排序,每一趟归并,其关键字比较 次数不超过n,元素移动次数都是n,因此归并排序的时间复杂度为O(nlog2n)

      ②

      用顺序表实现归并排序时,需要和待排序记录个数相等的辅助存储空间,所以空间复杂度为O(n)

    算法特点

      (1)      是稳定排序

      (2)      可用于链式结构,且不需要附加存储空间,但递归实现时仍需要开辟相应的递归工作栈

  • 相关阅读:
    Java面向对象
    JBCD技术
    初识数据库(其他数据库对象)
    初识数据库(TCL语句)
    初识数据库(分组函数)
    初识数据库(函数)
    初识数据库(数据类型)
    Java中的IO流
    Java中的线程
    Java中的集合
  • 原文地址:https://www.cnblogs.com/huxiaoyang/p/12058011.html
Copyright © 2020-2023  润新知