图解Java经典算法归并排序的原理与实现

图解Java经典算法归并排序的原理与实现

算法原理

归并排序是一种基于分治思想的排序算法,它将一个大的问题分解成若干个子问题,然后将子问题拆分到足够小的规模,最后对每个小问题进行解决,最终合并所有解决得到原始问题的解决方案。归并排序的执行过程可以简单地描述为两个步骤,分别为“分”和“治”。

归并排序的第一个步骤是分解,它将原始数组分解成若干个子数组,每个子数组包含 n/2 个元素的子问题。这个过程一直重复直到每个子数组包含一个或零个元素。为了更好地说明这个过程,下面是一个示例:

假设我们有以下未排序的数组:

[23, 1, 45, 78, 87, 56, 12, 57]

我们使用归并排序对该数组进行排序,这个过程可以分成以下几个步骤:

  1. 分解:将原始数组分解成若干个子数组

    [23, 1, 45, 78, 87, 56, 12, 57] -> [23, 1, 45, 78] [87, 56, 12, 57]
    [23, 1, 45, 78] -> [23, 1] [45, 78]
    [23, 1] -> [23] [1]
    [45, 78] -> [45] [78]
    [87, 56, 12, 57] -> [87, 56] [12, 57]
    [87, 56] -> [87] [56]
    [12, 57] -> [12] [57]

  2. :合并每个子数组,将它们按照从小到大的顺序组合起来,获得最终的排序结果

    [23] [1] -> [1, 23]
    [45] [78] -> [45, 78]
    [87] [56] -> [56, 87]
    [12] [57] -> [12, 57]
    [1, 23] [45, 78] -> [1, 23, 45, 78]
    [12, 57] [56, 87] -> [12, 56, 57, 87]
    [1, 23, 45, 78] [12, 56, 57, 87] -> [1, 12, 23, 45, 56, 57, 78, 87]

算法实现

下面是归并排序的Java代码实现。在本示例中,mergeSort 方法接收一个整数类型的数组作为输入,并返回一个已排序的数组。

public class MergeSort {
    public static void main(String[] args) {
        int[] arr = {23, 1, 45, 78, 87, 56, 12, 57};
        int[] sortedArr = mergeSort(arr);
        System.out.println(Arrays.toString(sortedArr));
    }

    public static int[] mergeSort(int[] arr) {
        if (arr.length <= 1) {
            return arr;
        }

        int[] left = new int[arr.length / 2];
        int[] right = new int[arr.length - left.length];

        System.arraycopy(arr, 0, left, 0, left.length);
        System.arraycopy(arr, left.length, right, 0, right.length);

        left = mergeSort(left);
        right = mergeSort(right);

        return merge(left, right);
    }

    private static int[] merge(int[] left, int[] right) {
        int[] result = new int[left.length + right.length];
        int leftIdx = 0;
        int rightIdx = 0;
        int resIdx = 0;

        while (leftIdx < left.length && rightIdx < right.length) {
            if (left[leftIdx] < right[rightIdx]) {
                result[resIdx++] = left[leftIdx++];
            } else {
                result[resIdx++] = right[rightIdx++];
            }
        }

        while (leftIdx < left.length) {
            result[resIdx++] = left[leftIdx++];
        }

        while (rightIdx < right.length) {
            result[resIdx++] = right[rightIdx++];
        }

        return result;
    }
}

在上面的实现中,我们使用了递归的方式实现了分治的过程。当传入的数组小于等于一个元素时,我们直接返回该数组,否则,我们将该数组分成 leftright 两个数组,然后分别对它们调用 mergeSort 方法,递归地将 leftright 拆分直到长度为 1。在每次递归结束后,我们将 leftright 合并到同一个数组里面,并按照大小顺序排序。

示例说明

示例 1:普通数组排序

下面是一个普通的未排序数组:

[23, 1, 45, 78, 87, 56, 12, 57]

我们使用上面给出的 MergeSort Java类对该数组进行排序,最终排序结果为:

[1, 12, 23, 45, 56, 57, 78, 87]

示例 2:带有重复元素的数组排序

下面是另一个未排序的数组,里面包含重复元素:

[23, 1, 12, 78, 87, 56, 12, 57]

我们使用 MergeSort 对该数组进行排序,最终会得到以下结果:

[1, 12, 12, 23, 56, 57, 78, 87]

正如我们所期望的,该算法能够正确地处理重复元素,而不会对重复元素顺序进行错误的调整。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:图解Java经典算法归并排序的原理与实现 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • 如何实现线程安全的堆栈?

    以下是关于线程安全的堆栈的完整使用攻略: 什么是线程安全的堆栈? 线程安全的堆栈是指在线程环境下多线程可以同时访问堆栈中的元素而不出现不一致或程序崩溃等问题。在线程编程中,线程安全堆栈是非常重要的,因为多个线同时问堆栈,会出现线程争的问题,导致数据不一致或程序崩。 如何实现线程安全的堆? 为实现线程安全的堆栈,需要使用同步机制来保证多线程对栈的访问有序。常用…

    Java 2023年5月12日
    00
  • IDEA 连接数据库的实现方法

    下面是“IDEA 连接数据库的实现方法”的完整攻略及示例说明。 1. 使用JDBC连接数据库 1.1 引入JDBC依赖 在Maven的pom.xml文件中,添加MySQL或其他数据库的JDBC依赖。 例如,在连接MySQL时,可以添加如下依赖: <dependency> <groupId>mysql</groupId> &…

    Java 2023年6月1日
    00
  • Java实现简单的五子棋游戏示例代码

    一、介绍 五子棋是一种非常古老的中国传统游戏,它简单易懂,规则简单,同时又非常有趣,是大众化的棋类游戏之一。本文将介绍如何用 Java 语言实现一个简单的五子棋游戏,让小伙伴们体验一下自己编写游戏的快感。 二、准备工作 开发五子棋游戏需要熟悉 Java 语言的基础代码编写,同时需要掌握一些基础的图形界面编程知识,推荐使用 Swing 或 JavaFX 进行图…

    Java 2023年5月19日
    00
  • SpringBoot自动配置原理详解

    Spring Boot是一个非常流行的Java框架,它可以帮助开发人员快速构建基于Spring的应用程序。其中一个最重要的特性是自动配置,它可以根据应用程序的依赖关系和配置文件来自动配置应用程序。在本文中,我们将详细讲解Spring Boot自动配置的原理,并提供两个示例来演示如何使用自动配置。 Spring Boot自动配置原理 Spring Boot的自…

    Java 2023年5月15日
    00
  • Java有效处理异常的三个原则

    Java有效处理异常的三个原则,分别是:及早捕获、适当处理和完整释放资源。下面我将详细为您讲解这三个原则的具体内容和攻略。 一、及早捕获 及早捕获指的是,在程序运行时,应尽可能地在可能产生异常的地方进行异常捕获,防止异常向上传播导致程序崩溃。具体攻略如下: 在可能产生异常的方法或代码块中使用 try-catch 语句捕获异常,并在 catch 语句中打印异常…

    Java 2023年6月15日
    00
  • Struts1和struts2的区别_动力节点Java学院整理

    Struts1和Struts2的区别 什么是Struts1和Struts2 Struts1是一个基于MVC模式的Web应用框架,由Apache组织开发和维护,是早期Web开发中使用较为广泛的框架之一。 Struts2,原名WebWork,是Struts1的升级版,也是一个基于MVC模式的Web应用框架,由Apache组织维护。 Struts1和Struts2…

    Java 2023年5月20日
    00
  • java中对象调用成员变量与成员实例方法

    Java 中,对象调用成员变量和成员实例方法的过程是通过对象的引用来实现的。下面是完整的攻略: 对象调用成员变量 首先需要创建一个对象的实例,即对象的地址,然后通过对象的引用来调用成员变量。Java 中的成员变量可以分为类变量和实例变量。对于类变量,直接使用类名来调用即可。对于实例变量,则必须使用对象的引用来调用。 调用类变量 调用类变量可以直接使用类名,例…

    Java 2023年5月26日
    00
  • 使用Spring Data JDBC实现DDD聚合的示例代码

    使用Spring Data JDBC实现DDD聚合的示例代码是一个比较复杂的过程,需要在DDD(领域驱动设计)的思想指导下,设计实现聚合及其关联的实体、值对象等等。以下是一个完整的攻略: 一、设计实体和聚合 首先需要确定需要实现的实体和聚合,并了解其业务含义和关系。 示例一:订单聚合 假设我们设计的一个电商系统,需要实现订单聚合,聚合中包含订单及其关联的商品…

    Java 2023年5月20日
    00
合作推广
合作推广
分享本页
返回顶部