1、核心思想

归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。 若将两个有序表合并成一个有序表,称为 2-路归并,与之对应的还有多路归并。

对于给定的一组数据,利用递归与分治技术将数据序列划分成为越来越小的半子表,在对半子表排序后,再用递归方法将排好序的半子表合并成为越来越大的有序序列。

为了提升性能,有时我们在半子表的个数小于某个数(比如 15)的情况下,对半子表的排序采用其他排序算法,比如插入排序。

归并排序图示(降序):

2、代码示例

输入:int[] array = {22, 28, 15, 15, 21, 3, 11, 2, 25, 28, 28};

输出结果:[2, 3, 11, 15, 15, 21, 22, 25, 28, 28, 28]

通过两种方式实现归并排序:一种使用Fork-Join工具类实现,另一种未使用工具类,通过测试发现,当数据量在百万级甚至千万级的时候使用ForkJoin方式效率更佳。

InsertionSort 类:归并排序通用工具类,满足阈值时使用插入排序算法。

package cn.lspj.ch2.forkjoin.sort;

import java.util.Arrays;

/**

* 类说明:插入排序(升序)

*/

public class InsertionSort {

public static int[] sort(int[] array){

int currentValue; // 当前元素的值

for (int i = 0; i < array.length - 1; i++) {

int prexIndex = i; // 已经排好序的元素位置

currentValue = array[prexIndex + 1]; // 当前元素值(即待排序元素的值)

// 在已经排好序的元素中倒序寻找合适的位子,如果当前待排序元素值比比较元素值小,则将比较的元素往后移以一位

while (prexIndex >= 0 && currentValue < array[prexIndex]) {

// 将比较的元素往后移一位

array[prexIndex + 1] = array[prexIndex];

prexIndex--;

}

// while循环结束时,说明已经找到了当前元素合适的位置,插入即可

array[prexIndex+1] = currentValue;

}

return array;

}

}

MergeSort 类:归并排序逻辑类

package cn.lspj.ch2.forkjoin.sort;

import java.util.Arrays;

/**

* 类说明:归并排序

*/

public class MergeSort {

private static int[] sort(int[] array){

if(array.length <= 5){ // 设定一个阈值,满足条件使用插入排序

return InsertionSort.sort(array); // 使用插入排序

} else {

// 拆分数组,递归调用

int mid = array.length / 2;

int[] left = Arrays.copyOfRange(array,0,mid);

int[] rigth = Arrays.copyOfRange(array,mid,array.length);

return merge(sort(left),sort(rigth));

}

}

/**

* 归并排序:将两个排序好的数组合并成一个数组

* @param left

* @param right

* @return

*/

public static int[] merge(int[] left, int right[]) {

int[] result = new int[left.length + right.length];

for (int index = 0, i = 0, j = 0; index < result.length; index++) {

if(i >= left.length){ // 表示左边数组已经取值排序完,直接把右边数组值赋值给result即可

result[index] = right[j++];

} else if(j >= right.length){ // 表示右边数组已经取值排序完,直接把左边数组值赋值给result即可

result[index] = left[i++];

} else if(left[i] > right[j]){ // 如果左边数组值大于右边数组值,则将右边数组值赋值给result

result[index] = right[j++];

} else { // 如果右边数组值大于右边数组值,则将左边数组值赋值给result

result[index] = left[i++];

}

}

return result;

}

public static void main(String[] args) {

int[] array = {22, 28, 15, 15, 21, 3, 11, 2, 25, 28, 28};

int[] sort = sort(array);

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

}

}

执行结果如下:

ForkJoinSort 类:使用ForkJoin实现归并排序

package cn.lspj.ch2.forkjoin.sort;

import java.util.Arrays;

import java.util.concurrent.ForkJoinPool;

import java.util.concurrent.RecursiveTask;

/**

* 类说明:使用ForkJoin实现归并排序

*/

public class ForkJoinSort {

private static class FkTask extends RecursiveTask {

private final static int THRESHOLD = 5;

private int[] array;

public FkTask(int[] array){

this.array = array;

}

@Override

protected int[] compute() {

if(array.length <= THRESHOLD){

return InsertionSort.sort(array);

} else {

int mid = array.length / 2;

FkTask leftTask = new FkTask(Arrays.copyOfRange(array,0,mid));

FkTask rightTask = new FkTask(Arrays.copyOfRange(array,mid,array.length));

invokeAll(leftTask,rightTask);

return MergeSort.merge(leftTask.join(),rightTask.join());

}

}

public static void main(String[] args) {

int[] array = {22, 28, 15, 15, 21, 3, 11, 2, 25, 28, 28};

// new出池的实例

ForkJoinPool forkJoinPool = new ForkJoinPool();

// new出task的实例

FkTask fkTask = new FkTask(array);

// 调用池的invoke方法

int[] invoke = forkJoinPool.invoke(fkTask);

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

}

}

}

执行结果如下:

3、复杂度

时间复杂度:O(nlogn)

空间复杂度:O(n)

项目

方法

O6F2x

MEV8v9987

4rlXs

2012.04.08 03-00-25

FQ2QN

2012-11-21 17:57:36

3dQrK

z4f8I2658

用java实现归并,算法:JAVA实现归并排序相关推荐

  1. java实现归并算法

    这个程序不是我原创的,是我在学习别人的程序上改的,想重新写出来的原因就是:作为用户我调用一个工具,我给你个数组,你给我个排好的数组就好了,还要输入起始点和终点显得很不智能.(其实我就是把一行代码封装到 ...

  2. JAVA分析html算法(JAVA网页蜘蛛算法)

    近来有些朋友在做蜘蛛算法,或者在网页上面做深度的数据挖掘.但是遇到复杂而繁琐的html页面大家都望而却步.因为很难获取到相应的数据. 最古老的办法的是尝试用正则表达式,估计那么繁琐的东西得不偿失,浪费 ...

  3. java实现图片切割_【Java】K-means算法Java实现以及图像切割

    1.K-means算法简述以及代码原型 总的来讲,k-means聚类须要下面几个步骤: ①.初始化数据 ②.计算初始的中心点,能够随机选择 ③.计算每一个点到每一个聚类中心的距离.而且划分到距离最短的 ...

  4. 【Java】K-means算法Java实现以及图像分割

    1.K-means算法简述以及代码原型 数据挖掘中一个重要算法是K-means,我这里就不做详细介绍.如果感兴趣的话可以移步陈皓的博客: http://www.csdn.net/article/201 ...

  5. java实现dijkstra_Dijkstra算法java实现

    一.实验目的 通过本实验的学习理解Dijkstra算法,并且编码实现最短路径问题. 二.实验内容 本Dijkstra算法实验采用了java实现,所以解决方案也使用了java中的接口,有map映射还有s ...

  6. 通过网页查看服务器算法,java分析html算法(java网页蜘蛛算法示例)

    遇到复杂而繁琐的html页面大家都望而却步.因为很难获取到相应的数据. 最古老的办法的是尝试用正则表达式,估计那么繁琐的东西得不偿失,浪费我们宝贵的时间. 第二个办法用开源组织htmlparser的包 ...

  7. 【Java】排序算法 之 【归并排序】 总结

    目录 1.合并两个有序数组函数 2. 归并排序 3. 非递归实现归并排序 1.合并两个有序数组函数 在学习归并排序之前,我们需要掌握合并两个有序数组为一个有序数组的函数是如何实现的 /*** 合并两个 ...

  8. java代码隐藏面消除算法,java常面的几种排序算法

    冒泡排序 1.算法步骤: 1)比较相邻的元素.如果第一个比第二个大,就交换他们两个. 2)对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对.这步做完后,最后的元素会是最大的数. 3)针对所有 ...

  9. 【Java】——基础算法Java代码

    随学随更,方便复习 选择排序: package one;/*** @author 新时代好少年* @create 2022-07-08 8:02* 选择排序:时间复杂度O(n^2) 空间复杂度O(1) ...

最新文章

  1. css设置元素继承父元素宽度_前端新手必知-5种新型的CSS长度单位
  2. 《Android应用开发》——1.3节配置Eclipse
  3. springMvc解决json中文乱码
  4. XHTML Strict和Transitional 的区别
  5. 兴义高考八中2021成绩查询,兴义第八中学2021年录取分数线
  6. LeetCode LCP 34. 二叉树染色(树上DP)
  7. 数据结构与算法——二分查找与二叉排序树
  8. 多维数组元素的下标引用与指针访问
  9. 初始化bean(二)—— 缓存部分
  10. [Pytorch] BCELoss和BCEWithLogitsLoss(Sigmoid-BCELoss合成为一步)
  11. echart雷达图数据图形的填充颜色_数据可视化,职场数据分析都需要哪些常用的图表?...
  12. keychain 专研
  13. linux 随机函数,Linux系统产生随机数方法
  14. Java女生后来_那些主动的女生后来怎么样了?
  15. 在OpenFOAM中标记某些区域自适应加密
  16. DH-UAP(大华统一应用开发平台)简介
  17. Day42 JavaScript-2
  18. Android 框架学习1:EventBus 3.0 的特点与如何使用
  19. 中国菜刀能在linux上运行吗,【Web Shell】- 技术剖析中国菜刀
  20. 英国工党的歌曲‘耶路撒冷’

热门文章

  1. nodejs返回html与vue,vuejs和nodejs的区别是什么?
  2. Unity+SenseAR教程:用手势发射爱心【源码】
  3. ShadeGraph教程之节点详解1:Artistic Nodes
  4. 基础计算机构,基础计算与设计
  5. JavaScript符号基础
  6. 微软开始取消 Windows 10 对 32 位系统的支持
  7. Blender 2.82 发布,三维动画制作软件
  8. mysql编译安装原理_MySQL编译安装全过程
  9. python2和python3的默认编码_Python2和Python3中的字符串编码问题解决
  10. python做视频抽帧图_Python提取视频中图片的示例(按帧、按秒)