首页 > 其他分享 >归并排序

归并排序

时间:2022-08-26 17:45:56浏览次数:54  
标签:归并 拆分 元素 数组 有序 排序

package com.inforcreation;

import java.util.Arrays;

/**
 * 归并排序
 *
 * 归并排序(Merge sort)是建立在归并操作上的一种有效的排序算法,
 * 归并排序对序列的元素进行逐层折半分组,然后从最小分组开始比较排序,
 * 合并成一个大的分组,逐层进行,最终所有的元素都是有序的
 *
 *
 * 定义
 *
 * 归并排序(Merge Sort)是建立在归并操作上的一种有效,稳定的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。
 * 将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
 *
 *
 *

 先将数组递归拆分成长度最大为2的小数组

 拆分阶段完成

 再对拆分后的子数组里面的数字进行排序,将小的移到左边,大的移到右边

 这样所有的子数组都是有序的了

 将这些有序的子数组进行归并

 归并阶段完成

 */
public class Mergesort {


/**
 * 初始数组: {7,8,6,4,5,1,2,3};
 * 1:折半拆分
 *     索引为0-7
 *       第一次差分  (0-7)/2  得到数组长度是4    范围是: 0-3   元素为: 7  8 6  4
 *       第二次拆分 (0+3)/2   得到数组长度是2    范围是:0-1    元素为: 7  8
 *       第三次拆分(0+1)/2   得到数组长度是1    范围是:0      元素为: 7     由于只有一个元素不能继续拆分所以 第二次拆分就可以走else逻辑进行比较
 *    推演展开1:
 *      7<8 直接返回【7,8】的数组
 *     接着拆分范围2-3 的数组 【6 4】
 *       走else里面的逻辑
 *         交换后返回【4,6】数组
 *      最后走mergeArrays把两个有序数组链接成一个有序数组
 *     推演展开2:
 *       获取一个长度为两个有序数组容量的数组
 *         leftArray和 rightArray数组都从下表0开始(此时他们里面都只有2个元素)
 *           左值小于右值,左值放入新数组,索引index++,leftIndex++
 *           右值小于左值,右值放入新数组,索引index++,rightIndex++
 *            直到index<finalArrayLength的条件不再满足,返回一个新的有序数组
 */

    /**
     * 归并排序
     * @param source
     * @return
     */
    private static int[] mergeSort(int[] source) {
        //数组长度
        int sourceLen = source.length;
//        7,8,6,4
        //如果长度大于2就拆分
        if(sourceLen > 2){
            //计算中间分割的索引位置
            int midIndex = sourceLen / 2;
            //对分割位置左边的数组进行递归拆分知道数组长度<=2
            int[] leftArray = mergeSort(Arrays.copyOf(source,midIndex));
            //对分割位置右边的数组进行递归拆分知道数组长度<=2
            //       {7,8,6,4,5,1,2,3};
            int[] rightArray = mergeSort(Arrays.copyOfRange(source,midIndex,sourceLen));
            //上面的递归已经将左右两边的子数组排好序,将两个有序的数组合并为一个数组
            int[] mergeArray = mergeArrays(leftArray,rightArray);
            return mergeArray;
        }
        // 否则说明集合中只有一个或者两个元素,可以进行这两个元素的比较排序了
        else{
            // 如果条件成立,说明数组中只有一个元素,或者是数组中的元素都已经排列好位置了
            if(sourceLen == 1 || source[0] <= source[1]) {
                return source;
            } else {
                //交换左右的值,也就是对子数组中的值排序
                int target[] = new int[sourceLen];
                target[0] = source[1];
                target[1] = source[0];
                return target;
            }
        }
    }
    /**
     * 合并两个有序集合
     * @param leftArray
     * @param rightArray
     * @return
     */
    private static int[] mergeArrays(int[] leftArray, int[] rightArray) {
        //定义一个新的容纳两个子数组的新数组
        int[] finalArray = new int[leftArray.length + rightArray.length];
        //左边子数组的长度
        int leftArrayLength = leftArray.length;
        //右边子数组的长度
        int rightArrayLength = rightArray.length;
        //合并后新数组的长度
        int finalArrayLength = finalArray.length;
        //只需要以新数组的长度便利一次即可
//       {7,8,6,4,5,1,2,3};
        for(int index = 0,leftIndex = 0,rightIndex = 0;index < finalArrayLength;index++){
            //获取左边集合当前索引上的值
            int leftValue = leftIndex >= leftArrayLength?Integer.MAX_VALUE:leftArray[leftIndex];
            //获取右边集合当前索引上的值
            int rightValue = rightIndex >= rightArrayLength?Integer.MAX_VALUE:rightArray[rightIndex];
            //如果左边数组索引上的值<右边数组索引上的值,那么新数组就是左边数组索引上的值
            if(leftValue < rightValue){
                leftIndex++;
                finalArray[index] = leftValue;
            }
            //否则就取右边数组索引上的值
            else{
                rightIndex++;
                finalArray[index] = rightValue;
            }
        }
        return finalArray;
    }

}

 

标签:归并,拆分,元素,数组,有序,排序
From: https://www.cnblogs.com/wangbiaohistory/p/16628379.html

相关文章

  • leetcode147:对链表进行插入排序
    packagecom.mxnet;publicclassSolution147{publicstaticvoidmain(String[]args){}/***Q:给定单个链表的头head,使用插入排序对链......
  • [算法]区间归并
    问题分析有的时候,会遇到给定一系列的区间,求交集or并集,或者合并的题.这些题的解题方式比较通用个,做一个总结.会用到集合和归并排序的相关知识.两个区间的关系有六种......
  • 拓扑排序学习笔记
    前言在学习这篇文章之前,你需要了解的算法有:基本图论知识链式前向星(图的一种存储方式)了解队列、栈等简单数据结构的实现,用STL也行。什么是拓扑排序AOV网的定义......
  • 探索JS中Object对象的key及key的排序
    首先,JavaScript中Object对象的key均为string类型的值。不过Object对象可以接受任意类型的值作为它的key,原因在于,我们为某个Object对象设定key的过程中会触发JavaScript的......
  • leetcode148:排序链表
    packagecom.mxnet;publicclassSolution148{publicstaticvoidmain(String[]args){}/***给你链表的头结点head,请将其按升序排列并......
  • 堆排序
    packagecom.lianzhu.filemanage.utils;importjava.util.Stack;/***栈排序*@description:栈的特性:先进后出如空数组【】*@step1:有一串数字4,8,7,9,2,6......
  • el-tree只能同级拖拽排序
    <el-tree:data="treeData"node-key="id"draggable:allow-drop="allowDrop"@node-drop="handleDrop"></el-tree>主要是用到了allow-drop这个方法,然后去......
  • 2022-8-25 剑指offer-字典树-每日一题-二分/排序
    剑指OfferII063.替换单词难度中等25收藏分享切换为英文接收动态反馈在英语中,有一个叫做 词根(root) 的概念,它可以跟着其他一些词组成另一个较长的单词——我......
  • js 对象数组根据对象的某一个属性值来进行数据排序
    1、根据id值从小到大排序//模拟数据varlist=[{"id":5,"name":"小明","age":5},{"id":2,"name":"小红","age":12},{"id":3,"name":......
  • Java-Java集合排序
    一、ListMap排序修订记录版本是否发布2020-01-25v1.0是一、ListMap排序Java中list里面存放map,根据map中的某一个或多个字段进行排序importjava.u......