[转载] Java实现归并排序(超详细,新手请进)

参考链接: Java中将数组合并为的新数组

归并排序 

大家好,这是我第一次在CSDN上写东西,因为我一直觉得有需要就去找别人的blog看看就好,但我发现自己写出来的东西确实能加深记忆。我半路出家,属实是个菜鸟,文章也许写的会有很多问题,还望大家多多包涵,欢迎指正。 最近在学数据结构,数据结构作为程序员该有的基本内功,无疑是我们要多加练习的。然而最为菜鸟的我,在学习的过程中也发现很多坑在大佬眼里不就是一句话的事 ,我写的这些既是为了帮助有需要的人,也是对自己的锻炼以及记录。废话到此结束,再多说要被锤了。 

代码打头 

~~废话不多说先上代码,如果代码都跑不出,大家就可以散了。~~ 

 

 

import java.util.Arrays;

 

public class mergeSortDemo {

    public static void main(String[] args) {

        int arr[] = new int[10];

        for (int i = 0;i<arr.length;i++){

            arr[i] = (int) (Math.random()*100);

        }

        for (int i=0;i<arr.length;i++){

            System.out.print(arr[i]+" ");

        }

        System.out.println("~~~~~~~~~~");

        mergeSort(arr,0,9);

    }

 

    public static void merge(int arr[],int low,int mid,int high){

        int i = low;

        int j = mid+1;

        int t = 0;

        int temp[] = new int[high-low+1];

        while (i<=mid && j<=high){

            if (arr[i]<arr[j]){

                temp[t++] = arr[i++];

            }

            else {

                temp[t++] = arr[j++];

            }

        }

        //

        while (i<=mid){

            temp[t++] = arr[i++];

        }

        while (j<=high){

            temp[t++] = arr[j++];

        }

        //

        for (int tempLeft=0;tempLeft<temp.length;tempLeft++){

            arr[low+tempLeft] = temp[tempLeft];

        }

    }

    public static void mergeSort(int arr[],int low,int high){

        int mid = (low+high)/2;

        if (low<high) {

            mergeSort(arr, low, mid);

            mergeSort(arr, mid+1, high);

            //

            merge(arr,low,mid,high);

            System.out.println( Arrays.toString(arr));

        }

    }

}

 

 

 

是不是被这精妙的逻辑给迷住了。 何谓归并排序,归并排序就是divide-and-merge。 

如图,算法的基本做法是:先分割数字,再按照每组的的大小排序,两个小组变为中组,两个中组合为大组。  

整体思路 

归并排序首先需要将数组拆分,然后治之。具体为,将一串数组分为两半,再各自对两半继续拆分,直至每组的的元素个数为一。此时开始治:如图中将数据分到最后一步,则上层长度为2,用当前的两个数组,按照算法来排序整合merge(){① 比较两个数组中的每一个数,将当前索引指向的较小的数装入临时数组temp中;② 当一组数据全部装入temp中时,一定会出现一种情况,另一组一定还有数据没存进去,所以将剩下的数存入temp;③ 这是比较难想到的一点:存入temp后,还需要返回到原先数组arr【】中去。但注意,虽然每次都是返回去的下标都是从0—>length-1,但不是一次性的。因为整个排序不是一次排好,每次小组内排完就需要存回arr,由此可知,不可能只用回传一次,但每次当然要把所有数据都穿回去,但是是分批进行,这也是这个算法的难点与精髓所在。为了方便理解,我用迭代的方式向大家展示:最后一次(也是最接近排序完成的一次)是两个数组合并为一个,这一个temp传回给arr【】,是从temp【0】->temp【length-1】。倒数第二次:temp【0】->temp【mid】,temp【mid+1】->temp【length-1】…第一次:两两回传,(可能是)temp【0】->temp【1】,temp2->temp3依次类推。这就肯定需要循环来定位索引。 

到此可以将上述方法抽象为 mergeSort()和merge()。mergeSort()多次递归调用自己而每次调用意味着分,分则要治,治则是在调用后用merge()。 

从图上可以清晰的看出,整个操作是栈式操作,先分的最后再合,当然递归本身就是栈式操作,我之所以这样说是为了让大家再顺着思路分析下来能知道如何去编写这样的程序。有了这些,我们开始逐句翻译就好了。 我们知道需要一个分的总函数以及每次帮忙合的子函数,总函数递归调用自己和子函数就完成了。故此,我们开始子函数的编写,也是按照之前的思路。 

实现 

merge(){①比较两个数组中的每一个数,将当前索引指向的较小的数装入临时数组temp中; 

merge(int arr[],int low,int mid,int high){

            int i = low;

            int j = mid+1;

            int t = 0;

            int temp[] = new int[high-low+1];

        while (i<=mid && j<=high){

            if (arr[i]<arr[j]){

                temp[t++] = arr[i++];

            }

            else {

                temp[t++] = arr[j++];

            }

 

 

②当一组数据全部装入temp中时,一定会出现一种情况,另一组一定还有数据没存进去,所以将剩下的数存入temp; 

 while (i<=mid){

            temp[t++] = arr[i++];

        }

        while (j<=high){

            temp[t++] = arr[j++];

        }

 

 

③ 这是比较难想到的一点:存入temp后,还需要返回到原先数组arr【】中去。但注意,虽然每次都是返回去的下标都是从0—>length-1,但不是一次性的。因为整个排序不是一次排好,每次小组内排完就需要存回arr,由此可知,不可能只用回传一次,但每次当然要把所有数据都穿回去,但是是分批进行,这也是这个算法的难点与精髓所在。为了方便理解,我用迭代的方式向大家展示:最后一次(也是最接近排序完成的一次)是两个数组合并为一个,这一个temp传回给arr【】,是从temp【0】->temp【length-1】。倒数第二次:temp【0】->temp【mid】,temp【mid+1】->temp【length-1】…第一次:两两回传,(可能是)temp【0】->temp【1】,temp2->temp3依次类推。这就肯定需要循环来定位索引。 

for (int tempLeft=0;tempLeft<temp.length;tempLeft++){

            arr[low+tempLeft] = temp[tempLeft];

        }

 

 

mergeSort()多次递归调用自己而每次调用意味着分,分则要治,治则是在调用后用merge()。 我们都知道要一分为二二分为四,到元素为一时结束,反过来怎么写循环呢。当length=1 则(0+1)/2=0 此时low=high 反过来 low<high则可以不停分解 

mergeSort(int arr[],int low,int high){

        int mid = (low+high)/2;

        if (low<high) {

            mergeSort(arr, low, mid);

            mergeSort(arr, mid+1, high);

            //

            merge(arr,low,mid,high);

            System.out.println( Arrays.toString(arr));

        }

    }

 

 

分析 

首先要将整个数组遍历一遍,归并排序要进行log2n次,总共的时间复杂度为O(nlog2n) 

递归深度为log2n 额外的数组空间 n 总的空间复杂度为O(n+log2n) 

再merge()中使用的是两两比较,不存在跳跃,所以归并排序是稳定的。 

换而言之,归并排序是一种空间换时间的算法。 

谢谢大家。 

图侵删

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/540165.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

centos6设置静态IP

#编辑配置文件,添加修改以下内容 vim /etc/sysconfig/network-scripts/ifcfg-eth0 BOOTPROTOstatic #启用静态IP地址 ONBOOTyes #开启开机自动启用网络连接 IPADDR192.168.21.129 #设置IP地址 NETMASK255.255.255.0 #设置子网掩码 GATEWAY192.168…

[转载] 1022 D进制的A+B (20分)【java题解】【80ms】

参考链接&#xff1a; Java流Stream 题解 使用 toUnsignedString&#xff08;&#xff09;即可 我有仔细读过toUnsignedString&#xff08;&#xff09;&#xff0c;有兴趣可以看看 第3章 java的基本程序设计结构【补缺学习】【注释与数据类型】【核心技术卷I】 impor…

mysql 5.6.4以上版本innodb支持全文索引的测试

对于mysql 5.6.4以上版本innodb支持全文索引的测试 在mysql官网&#xff0c;innodb引擎在5.6.4版本提供了对全文索引的支持&#xff0c;笔者对此做了测试&#xff0c;发现对中文全文检索的支持依然不理想&#xff0c;但却确实提供了对英文的全文支持。 12.9.5 Full-Text Restri…

[转载] Java字符串分割方法

参考链接&#xff1a; Java中的StringTokenizer方法的示例 2 [sizemedium]1.用split()方法进行分割&#xff0c;分割开的子字符串放入数组&#xff0c;然后进行处理。 示例代码如下&#xff1a; public class SplitTest { /** * param args * author colin */ …

[转载] Java StringBuilder StringJoiner

参考链接&#xff1a; 何时在StringBuilder上使用StringJoiner 1. StringBuilder Java编译器对String做了特殊处理&#xff0c;使得我们可以直接用拼接字符串。 虽然可以直接拼接字符串&#xff0c;但是&#xff0c;在循环中&#xff0c;每次循环都会创建新的字符串对象&a…

EMC VMAX的磁盘构成,fast policy(重要)

首先是流程&#xff0c; 不同种类的磁盘&#xff08;sata&#xff0c;fc&#xff0c;flah&#xff09;->disk group->raid->DATA volume->thin pool->TDEV and BCVDEV (lun) 然后细看&#xff1a; 1&#xff09; 不同种类的磁盘叫做disk&#xff0c;这是可见的物…

[转载] Java反射是什么?看这篇绝对会了!

参考链接&#xff1a; Java中的util.Arrays与Reflection.Array的示例 作者&#xff1a;火星十一郎 https://www.cnblogs.com/hxsyl 一.概念 反射就是把Java的各种成分映射成相应的Java类。 Class类的构造方法是private&#xff0c;由JVM创建。 反射是java语言的一个特性…

[精讲-3]Offline Domain Join

从windows 2008 ,windows 7开始起就具备脱机加入域的功能,就是它们在未连接DC的情况下,也可以加入域. 假如环境lab.com ,一台已加入域的PC (WIN7Client) 和即将加入域的PC(win7-2) 在win7client上run下面这个命令 DC已作了一次预先的动作:创建了computer object 在win7-2上,用本…

[转载] Java——toArray,集合转换为数组

参考链接&#xff1a; 从ArrayList到Java的Array数组转换&#xff1a;toArray()方法 package day04; import java.util.ArrayList; import java.util.Collection; /** * 集合转换为数组 * Collection中定义了两个方法 * Object[] toArray * <T>Y[] toArray(T[] array) …

c#匿名方法

//以下示例和说明都源于《visual c# 2005 技术内幕》 //匿名函数就是没有名字的函数&#xff0c;是专用于委托的函数。 using System; using System.Collections.Generic; using System.Text; namespace 匿名方法 { public delegate void DelegateClass(); public dele…

[转载] JAVA8 创建流的5种方式

参考链接&#xff1a; 用Java创建流的10种方法 java8中的流式操作是一个很重要的内容 1、通过 stream 方法把 List 或数组转换为流&#xff0c;如Arr.stream()&#xff1b; //通过stream方法把List或数组转换为流 Arrays.asList("a1", "a2", "a3&…

用户反馈:对 Rafy 开发框架的一些个人建议

对Rafy开发框架的一些个人建议 1、潜在使用群体分析 个人认为使用类似Rafy、AgileEAS.NET、PDF.NET及OpenWorks框架的群体主要为以下几种&#xff1a; 1.1、小微软件企业 小微软件企业&#xff0c;这类软件公司的开发人员一般在10人以下&#xff0c;多以项目实施为主基本谈不上…

[转载] Java8新特新--Stream语法应用在ArrayList的元素移除和排序

参考链接&#xff1a; 如何在Java 8中打印Stream的元素 单元测试&#xff1a; Test public void Test02(){ // 源 ArrayList<Integer> IdsSour new ArrayList<>(); IdsSour.add(5); IdsSour.add(1); IdsSour.add(3); IdsSour.add(2); IdsSour.add(6); IdsSour.a…

搭建iscsi存储系统

搭建iscsi存储系统 NAS和SAN服务器概述 NAS网络附属存储&#xff1a; NAS&#xff08;Network Attached Storage)&#xff0c;NAS服务器是连接在网络上&#xff0c;具备资料存储功能的服务器&#xff0c;一种与用数据存储服务器。网络附属存储基于标准网络协议&#xff08;Tcp/…

[转载] Java8 Stream流遍历 如何使用索引

参考链接&#xff1a; Java 8中迭代带有索引的流Stream 1. 问题来源 Java8的Stream流为我们的遍历集合带来了方便&#xff0c;基本可以取代for循环了。但是有一些情况需要知道当前遍历的索引&#xff0c;使用for循环当然可以轻易获得&#xff0c;但使用stream就很难了。 比如…

Jquery简单的右侧浮动菜单

今天有空稍微看了下Jquery动画函数animate这个方法&#xff0c;发现可以用这个方法来做下简单的右侧浮动菜单 因为经常做淘宝页面时候会碰到这样的效果 以前都是用人家的javascript组件代码 发现老是用人家也不好&#xff0c;所以今天有空用jqeury中的animate这个方法写了一个简…

[转载] Java8-Stream API 详解

参考链接&#xff1a; 如何在Java 8中从Stream获取ArrayList 摘要 Stream 作为 Java 8 的一大亮点&#xff0c;它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念。它也不同于 StAX 对 XML 解析的 Stream&#xff0c;也不是 Amazon Kinesis 对大数据实时处理…

在Microsoft System Center中利用您的现有投资管理VMware--Veeam MP v6.5

在 Microsoft System Center 中利用您的现有投资管理 VMware VeeamManagement Pack (MP) v6.5 适用于物理、虚拟和备份基础架构的单一的虚拟管理平台 前段时间介绍了Veeam Management Pack (MP) v6.0产品&#xff0c;昨天发布了新版本VeeamManagement Pack (MP) v6.5&#xff0…

[转载] Java关键字(Java 8版本)

参考链接&#xff1a; 所有Java关键字列表 定义 被Java语言赋予了特殊含义&#xff0c;用作专门用途的字符串&#xff08;单词&#xff09;&#xff0c;这些关键字不能用于常量、变量、和任何标识符的名称。 Java关键字(Java 8版本) Java关键字(Java 8 以后版本) 注意事…

uiw 1.2.17 发布,基于 React 16 的组件库

发布&#xff0c; 高品质的UI工具包&#xff0c;React 16的组件库。 文档网站&#xff1a;uiw-react.github.io开源仓库&#xff1a;github.com/uiw-react/u… 更新内容&#xff1a; ? 修复没有代码检测文件匹配*.css。 5712887 ? 添加 .editorconfig 文件. d82dabf ⛑ 给测试…