排序算法(归并排序)

  关于排序算法,常见的大致有:冒泡排序、插入排序、选择排序、快速排序、归并排序、桶排序、计数排序等。每一种排序算法都有它们各自的优劣和适用场景。一般可以从这么几个角度来衡量排序算法:

  1.最好时间复杂度、最坏时间复杂度、平均时间复杂度

  2.是否是原地排序算法:原地排序算法,指空间复杂度为O(1)

  3.是否是稳定排序算法:稳定排序算法,指如果待排序序列中有值相等的元素,经过排序之后,值相等元素的顺序保持不变

  关于归并排序:

#综述:
    1.冒泡排序、插入排序、选择排序算法的时间复杂度都是O(n^2)。只适合小规模数据的排序
    2.归并排序、快速排序算法的时间复杂度是O(nlogn)。适合大规模数据的排序
    3.归并排序、快速排序算法都应用了分治思想
    
#描述归并排序:
    归并排序的核心思想,就是分而治之。比如要排序一个数组,先把数据从中间分成前后两个部分,然后对前后两部分分别排序,再将排好序的两部分进行合并。最终整个数组就排好序了。
    
#实现公式:
    地推公式:
        merge_sort(p…r) = merge(merge_sort(p…q), merge_sort(q+1…r))

    终止条件:
        p >= r 不用再继续分解

  代码实现:

package com.anan.algorithm;

import java.util.Arrays;

/**
 * 归并排序
 */
public class MergeSort {

    public static void main(String[] args) {
        int[] a={4,5,6,3,2,1,8,9,12,11,8};
        System.out.println("排序前:"+ Arrays.toString(a));

        // 排序
        mergeSort(a,0,a.length-1);

        System.out.println("排序后:"+Arrays.toString(a));
    }

    // 第一步:拆分
    public static void mergeSort(int[] a,int left,int right){
        // 递归终止条件
        if(left>=right)return ;

        // 计算中间位置
        int mid = (left+right)/2;
        // 中间位置向左方向,左边继续拆分
        mergeSort(a,left,mid);
        // 中间位置向右方向,右边继续拆分
        mergeSort(a,mid+1,right);

        // 合并的过程
        merge(a,left,mid+1,right);
    }

    // 第二步:合并
    /**
     *  参数:
     *      a:数组
     *      left:指向数组第一个元素
     *      mid:指向数组分割元素
     *      right:指向数组最后一个元素
     */
    public static void merge(int[] a,int left,int mid,int right){
        // 左边数组大小
        int[] leftA = new int[mid-left];
        // 右边数组大小
        int[] rightA = new int[right-mid+1];

        // 左边数组填充数据
        for(int i=left;i<mid;i++){
            leftA[i-left]=a[i];
        }

        // 右边数组填充数据
        for(int j=mid;j<=right;j++){
            rightA[j-mid]=a[j];
        }

        // 定义两个位置指针
        int L_INDEX=0,R_INDEX=0;
        // a数组第一个元素位置
        int k=left;

        // 比较两个数组的值,将小的一个放入数组a中
        while(L_INDEX<leftA.length && R_INDEX<rightA.length){
            // 谁比较小,谁将元素放入大数组中,移动指针,继续比较下一个
            if(leftA[L_INDEX] < rightA[R_INDEX]){
                a[k]=leftA[L_INDEX];

                // 移动位置
                L_INDEX++;
                k++;
            }else{
                a[k] = rightA[R_INDEX];

                // 移动位置
                R_INDEX++;
                k++;
            }

        }

        // 如果左边的数组还没有比较完成。右边的数组已经比较完成。则将左边余下的数直接放入大数组a中
        while(L_INDEX<leftA.length){
            a[k] = leftA[L_INDEX];

            // 移动位置
            L_INDEX++;
            k++;
        }

        // 如果右边的数组还没有比较完成。左边的数组已经比较完成。则将右边余下的数直接放入大数组a中
        while(R_INDEX<rightA.length){
            a[k] = rightA[R_INDEX];

            // 移动位置
            R_INDEX++;
            k++;
        }

    }
}

  

原文地址:https://www.cnblogs.com/itall/p/11137739.html