java实现归并排序(详细解释代码和逻辑)

简介: java实现归并排序(详细解释代码和逻辑)

归并排序(Merge Sort)是一种基于分治法的排序算法。它将数组分成两个子数组,分别进行排序,然后合并这两个有序的子数组。其时间复杂度为O(n log n),空间复杂度为O(n)。下面是用Java实现归并排序的代码以及详细的注释和两个代码例子。

归并排序的实现代码

public class MergeSort {
 
    // 主函数,负责调用归并排序函数
    public static void main(String[] args) {
        int[] array = {12, 11, 13, 5, 6, 7};
        System.out.println("给定数组:");
        printArray(array);
 
        MergeSort ms = new MergeSort();
        ms.sort(array, 0, array.length - 1);
 
        System.out.println("\n排序后的数组:");
        printArray(array);
    }
 
    // 归并排序函数
    void sort(int[] array, int left, int right) {
        if (left < right) {
            // 找出中间点
            int middle = (left + right) / 2;
 
            // 对左半部分进行排序
            sort(array, left, middle);
            // 对右半部分进行排序
            sort(array, middle + 1, right);
 
            // 合并两个有序子数组
            merge(array, left, middle, right);
        }
    }
 
    // 合并两个有序子数组的函数
    void merge(int[] array, int left, int middle, int right) {
        // 找出两个子数组的大小
        int n1 = middle - left + 1;
        int n2 = right - middle;
 
        // 创建临时数组
        int[] leftArray = new int[n1];
        int[] rightArray = new int[n2];
 
        // 拷贝数据到临时数组
        for (int i = 0; i < n1; ++i)
            leftArray[i] = array[left + i];
        for (int j = 0; j < n2; ++j)
            rightArray[j] = array[middle + 1 + j];
 
        // 合并临时数组
 
        // 初始索引
        int i = 0, j = 0;
 
        // 合并数组
        int k = left;
        while (i < n1 && j < n2) {
            if (leftArray[i] <= rightArray[j]) {
                array[k] = leftArray[i];
                i++;
            } else {
                array[k] = rightArray[j];
                j++;
            }
            k++;
        }
 
        // 拷贝剩余元素
        while (i < n1) {
            array[k] = leftArray[i];
            i++;
            k++;
        }
 
        while (j < n2) {
            array[k] = rightArray[j];
            j++;
            k++;
        }
    }
 
    // 打印数组
    static void printArray(int[] array) {
        int n = array.length;
        for (int i = 0; i < n; ++i)
            System.out.print(array[i] + " ");
        System.out.println();
    }
}

代码解析

主函数main:初始化一个数组,调用sort方法进行归并排序,并打印排序前后的数组。


排序函数sort:


检查left是否小于right,如果是则继续分割数组。

计算数组中间位置middle。

递归地对左半部分和右半部分进行排序。

调用merge函数合并排序后的左右两部分。

合并函数merge:


计算左右两个子数组的大小。

创建临时数组并将数据拷贝到临时数组。

使用两个指针i和j分别指向左右子数组的起始位置,比较两个指针对应的元素,将较小的元素放入原数组中。

拷贝剩余元素(如果有的话)到原数组中。

打印数组函数printArray:简单地遍历数组并打印每个元素。

代码示例1:排序一个包含重复元素的数组

public class MergeSortExample1 {
    public static void main(String[] args) {
        int[] array = {4, 5, 3, 3, 1, 2, 2, 4};
        System.out.println("给定数组:");
        printArray(array);
 
        MergeSort ms = new MergeSort();
        ms.sort(array, 0, array.length - 1);
 
        System.out.println("\n排序后的数组:");
        printArray(array);
    }
 
    static void printArray(int[] array) {
        for (int i : array)
            System.out.print(i + " ");
        System.out.println();
    }
}

示例1输出

给定数组:
4 5 3 3 1 2 2 4 
 
排序后的数组:
1 2 2 3 3 4 4 5 

代码示例2:排序一个包含负数的数组

public class MergeSortExample2 {
    public static void main(String[] args) {
        int[] array = {0, -10, 5, -3, 8, 7, -1, 4};
        System.out.println("给定数组:");
        printArray(array);
 
        MergeSort ms = new MergeSort();
        ms.sort(array, 0, array.length - 1);
 
        System.out.println("\n排序后的数组:");
        printArray(array);
    }
 
    static void printArray(int[] array) {
        for (int i : array)
            System.out.print(i + " ");
        System.out.println();
    }
}

示例2输出

给定数组:
0 -10 5 -3 8 7 -1 4 
 
排序后的数组:
-10 -3 -1 0 4 5 7 8 
相关文章
|
7天前
|
安全 Java API
Java 17新特性让你的代码起飞!
【10月更文挑战第4天】自Java 8发布以来,Java语言经历了多次重大更新,每一次都引入了令人兴奋的新特性,极大地提升了开发效率和代码质量。本文将带你从Java 8一路走到Java 17,探索那些能让你的代码起飞的关键特性。
31 1
|
10天前
|
Java 数据库连接 Maven
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
这篇文章介绍了如何在Spring Boot项目中整合MyBatis和MyBatis Generator,使用逆向工程来自动生成Java代码,包括实体类、Mapper文件和Example文件,以提高开发效率。
36 2
mybatis使用一:springboot整合mybatis、mybatis generator,使用逆向工程生成java代码。
|
10天前
|
存储 缓存 Java
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
这篇文章详细介绍了Java中的IO流,包括字符与字节的概念、编码格式、File类的使用、IO流的分类和原理,以及通过代码示例展示了各种流的应用,如节点流、处理流、缓存流、转换流、对象流和随机访问文件流。同时,还探讨了IDEA中设置项目编码格式的方法,以及如何处理序列化和反序列化问题。
38 1
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
|
6天前
|
Java 程序员 API
Java中的Lambda表达式:简化代码的秘密武器
【10月更文挑战第11天】 在Java编程中,Lambda表达式是一种简洁而强大的工具,它允许我们将函数作为参数传递给其他方法。本文将介绍Lambda表达式的基本概念、使用方法以及在实际项目中的应用案例,帮助你更好地理解和利用这一特性来简化代码。
20 8
|
4天前
|
Java 开发者
在Java编程中,正确的命名规范不仅能提升代码的可读性和可维护性,还能有效避免命名冲突。
【10月更文挑战第13天】在Java编程中,正确的命名规范不仅能提升代码的可读性和可维护性,还能有效避免命名冲突。本文将带你深入了解Java命名规则,包括标识符的基本规则、变量和方法的命名方式、常量的命名习惯以及如何避免关键字冲突,通过实例解析,助你写出更规范、优雅的代码。
24 3
|
4天前
|
Java 程序员
在Java编程中,关键字不仅是简单的词汇,更是赋予代码强大功能的“魔法咒语”。
【10月更文挑战第13天】在Java编程中,关键字不仅是简单的词汇,更是赋予代码强大功能的“魔法咒语”。本文介绍了Java关键字的基本概念及其重要性,并通过定义类和对象、控制流程、访问修饰符等示例,展示了关键字的实际应用。掌握这些关键字,是成为优秀Java程序员的基础。
11 3
|
9天前
|
jenkins Java 测试技术
如何使用 Jenkins 自动发布 Java 代码,通过一个电商公司后端服务的实际案例详细说明
【10月更文挑战第8天】本文介绍了如何使用 Jenkins 自动发布 Java 代码,通过一个电商公司后端服务的实际案例,详细说明了从 Jenkins 安装配置到自动构建、测试和部署的全流程。文中还提供了一个 Jenkinsfile 示例,并分享了实践经验,强调了版本控制、自动化测试等关键点的重要性。
21 5
|
12天前
|
并行计算 Java API
探索Java中的Lambda表达式:简化代码,提高可读性
【10月更文挑战第5天】Lambda表达式在Java 8中引入,旨在简化集合操作和并行计算。本文通过介绍Lambda表达式的基本概念、语法结构以及实际应用示例,展示了如何利用这一特性编写更加简洁、易读的代码。我们将从Lambda的基础入手,逐步深入到其在函数式接口中的应用,并探讨其对Java编程范式的影响。
|
13天前
|
消息中间件 存储 Java
大数据-58 Kafka 高级特性 消息发送02-自定义序列化器、自定义分区器 Java代码实现
大数据-58 Kafka 高级特性 消息发送02-自定义序列化器、自定义分区器 Java代码实现
27 3
|
7天前
|
Java 编译器 API
从Java 8到Java 17,这些新特性让你的代码起飞!
【10月更文挑战第10天】在软件开发领域,Java作为一种历史悠久且广泛使用的编程语言,不断进化以适应新的需求和挑战。从Java 8到Java 17,每一次版本更新都带来了诸多新特性和改进,极大地提升了开发效率和代码质量。今天,我们就来一起探讨这些新特性,看看它们是如何让我们的代码“起飞”的。
69 0