Arrays.sort的粗略讲解
排序算法,基本的高级语言都有一些提供。C语言有qsort()函数,C++有sort()函数,java语言有Arrays类(不是Array)。用这些排序时,都可以写自己的排序规则。
Java API对Arrays类的说明是:此类包含用来操作数组(比如排序和搜索)的各种方法。
1.对基本数据类型的数组的排序
说明:(1)Arrays类中的sort()使用的是“经过调优的快速排序法”;
(2)比如int[],double[],char[]等基数据类型的数组,Arrays类之只是提供了默认的升序排列,没有提供相应的降序排列方法。
(3)要对基础类型的数组进行降序排序,需要将这些数组转化为对应的封装类数组,如Integer[],Double[],Character[]等,对这些类数组进行排序。(其实还不如先进行升序排序,自己在转为将序)。
用默认的升序对数组排序
函数原型:static void sort(int[] a) 对指定的 int 型数组按数字升序进行排序。
static void sort(int[] a, int fromIndex, int toIndex) 对指定 int 型数组的指定范围按数字升序进行排序。
源代码解释:
/**
* Sorts the specified array into ascending numerical order.
*
* <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
* by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
* offers O(n log(n)) performance on many data sets that cause other
* quicksorts to degrade to quadratic performance, and is typically
* faster than traditional (one-pivot) Quicksort implementations.
*
* @param a the array to be sorted
*/
第一部分:
首先介绍排序里面会调用的插入排序,什么时候会调用这段代码,在代码的最后面有解释
下面我来具体讲解这段代码,INSERTION_SORT_THRESHOLD是是否采用插入排序的阈值
代码中设置为47,当小于排序长度小于47时,调用下面这块代码
leftmost是boolean类型,如果是true表示是从第一个位置开始往后排序,如果不是,说明是从中间任意位置开始排序
如果leftmost是true的时候,采用最原始的插入排序方法,
如果是false的时候,采用优化的插入排序方法,pair insertion sort,每次对两个数据进行插入,提高了效率
/**
* Sorts the specified range of the array by Dual-Pivot Quicksort.
*
* @param a the array to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
* @param leftmost indicates if this part is the leftmost in the range
*/
private static void sort(int[] a, int left, int right, boolean leftmost) {
int length = right - left + 1;
// Use insertion sort on tiny arrays
if (length < INSERTION_SORT_THRESHOLD) {
if (leftmost) {
/*
* Traditional (without sentinel) insertion sort,
* optimized for server VM, is used in case of
* the leftmost part.
*/
for (int i = left, j = i; i < right; j = ++i) {
int ai = a[i + 1];
while (ai < a[j]) {
a[j + 1] = a[j];
if (j-- == left) {
break;
}
}
a[j + 1] = ai;
}
} else {
/*
* Skip the longest ascending sequence.
*/
do {
if (left >= right) {
return;
}
} while (a[++left] >= a[left - 1]);
/*
* Every element from adjoining part plays the role
* of sentinel, therefore this allows us to avoid the
* left range check on each iteration. Moreover, we use
* the more optimized algorithm, so called pair insertion
* sort, which is faster (in the context of Quicksort)
* than traditional implementation of insertion sort.
* 具体执行过程:上面的do-while循环已经排好的最前面的数据
*(1)将要插入的数据,第一个值赋值a1,第二个值赋值a2,
*(2)然后判断a1与a2的大小,使a1要大于a2
*(3)接下来,首先是插入大的数值a1,将a1与k之前的数字一一比较,直到数值小于a1为止,把a1插入到合适的位置,注意:这里的相隔距离为2
*(4)接下来,插入小的数值a2,将a2与此时k之前的数字一一比较,直到数值小于a2为止,将a2插入到合适的位置,注意:这里的相隔距离为1
*(5)最后把最后一个没有遍历到的数据插入到合适位置
*/
for (int k = left; ++left <= right; k = ++left) {
int a1 = a[k], a2 = a[left];
if (a1 < a2) {
a2 = a1; a1 = a[left];
}
while (a1 < a[--k]) {
a[k + 2] = a[k];
}
a[++k + 1] = a1;
while (a2 < a[--k]) {
a[k + 1] = a[k];
}
a[k + 1] = a2;
}
int last = a[right];
while (last < a[--right]) {
a[right + 1] = a[right];
}
a[right + 1] = last;
}
return;
}
。。。。。。//这里只截取了长度小于INSERTION_SORT_THRESHOLD的时候,大于的时候比较难,没具体分析
/**下面是INSERTION_SORT_THRESHOLD的解释
* If the length of an array to be sorted is less than this
* constant, insertion sort is used in preference to Quicksort.
*/
private static final int INSERTION_SORT_THRESHOLD = 47;
}
第二部分:
当要排队列长度小于QUICKSORT_THRESHOLD并且大于INSERTION_SORT_THRESHOLD时,用双基准快速排序方法,
这部分的代码就是上面。。。。没有显示的部分,具体的原理同双基准快速排序
第三部分:
如果要排序的队列长读大于INSERTION_SORT_THRESHOLD,采用合并排序方法
/**
* If the length of an array to be sorted is less than this
* constant, Quicksort is used in preference to merge sort.
*/
private static final int QUICKSORT_THRESHOLD = 286;
import java.util.Arrays;public class ArraysSort_11 {
public static void main(String args[])
{
int[] a={1,4,-1,5,0};
Arrays.sort(a);
//数组a[]的内容变为{-1,0,1,4,5}
for(int i=0;i<a.length;i++)
System.out.print(a[i]+" ");
}
}
2.对复合数据类型的数据的排序
函数原型: (1)public static<T> void sort(T[] a,Comparator c) 根据指定比较器产生的顺序对指定对象数组进行排序。
(2)public static<T> void sort(T[] a,int fromIndex,int toIndex,Comparator c) 根据指定比较器产生的顺序对指定对象数组的指定范围进行排序。
说明:这个两个排序算法是“经过调优的合并排序”算法。
源码:
其中的两个API
public static <T> void sort(T[] a, Comparator<? super T> c) {
if (LegacyMergeSort.userRequested)
legacyMergeSort(a, c);
else
TimSort.sort(a, c);
}
public static <T> void sort(T[] a, int fromIndex, int toIndex,
Comparator<? super T> c) {
if (LegacyMergeSort.userRequested)
legacyMergeSort(a, fromIndex, toIndex, c);
else
TimSort.sort(a, fromIndex, toIndex, c);
}
核心代码调用的是相同的代码
如果:LegacyMergeSort.userRequested为真时:
执行下面代码:
这里c可以为null,如果为null,则调用默认的比较器进行比较,否则调用用户指定的比较器进行比较。
下面是改进版的合并排序
执行步骤如下:
(1)如果比较的长度小于INSERTIONSORT_THRESHOLD插入排序的阈值,直接调用传统的插入排序进行比较
(2)当大于插入排序的阈值时,采用合并排序算法,这里有个改进的地方,加亮部分,如果已经排好序的,不再进行比较,而是直接复制过去,提高效率
private static void mergeSort(Object[] src,
Object[] dest,
int low, int high, int off,
Comparator c) {
int length = high - low;
// Insertion sort on smallest arrays
if (length < INSERTIONSORT_THRESHOLD) {
for (int i=low; i<high; i++)
for (int j=i; j>low && c.compare(dest[j-1], dest[j])>0; j--)
swap(dest, j, j-1);
return;
}
// Recursively sort halves of dest into src
int destLow = low;
int destHigh = high;
low += off;
high += off;
int mid = (low + high) >>> 1;
mergeSort(dest, src, low, mid, -off, c);
mergeSort(dest, src, mid, high, -off, c);
// If list is already sorted, just copy from src to dest. This is an
// optimization that results in faster sorts for nearly ordered lists.
if (c.compare(src[mid-1], src[mid]) <= 0) {
System.arraycopy(src, low, dest, destLow, length);
return;
}
// Merge sorted halves (now in src) into dest
for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
if (q >= high || p < mid && c.compare(src[p], src[q]) <= 0)
dest[i] = src[p++];
else
dest[i] = src[q++];
}
}
如果LegacyMergeSort.userRequested为假时,
调用TimSort.sort方法,如果c为null,还是调用上面的方法,
否则调用比较器进行比较
代码实例:
package aa;import java.util.Arrays;import java.util.Comparator;public class Arraysort {
Point[] arr;
Arraysort(){
arr=new Point[4]; //定义对象数组arr,并分配存储的空间
for(int i=0;i<4;i++)
arr[i]=new Point();
}
public static void main(String[] args) {
Arraysort sort=new Arraysort();
sort.arr[0].x=2;sort.arr[0].y=1; //初始化,对象数组中的数据
sort.arr[1].x=2;sort.arr[1].y=2;
sort.arr[2].x=1;sort.arr[2].y=2;
sort.arr[3].x=0;sort.arr[3].y=1;
Arrays.sort(sort.arr, new MyComprator()); //使用指定的排序器,进行排序
for(int i=0;i<4;i++) //输出排序结果
System.out.println("("+sort.arr[i].x+","+sort.arr[i].y+")");
}
}class Point{
int x;
int y;
}//比较器,x坐标从小到大排序;x相同时,按照y从小到大排序class MyComprator implements Comparator {
public int compare(Object arg0, Object arg1) {
Point t1=(Point)arg0;
Point t2=(Point)arg1;
if(t1.x != t2.x)
return t1.x>t2.x? 1:-1;
else
return t1.y>t2.y? 1:-1;
}
}
执行输出:
Arrays.sort的粗略讲解的更多相关文章
- Arrays.Sort()中的那些排序算法
本文基于JDK 1.8.0_211撰写,基于java.util.Arrays.sort()方法浅谈目前Java所用到的排序算法,仅个人见解和笔记,若有问题欢迎指证,着重介绍其中的TimSort排序,其 ...
- java源码分析:Arrays.sort
仔细分析java的Arrays.sort(version 1.71, 04/21/06)后发现,java对primitive(int,float等原型数据)数组采用快速排序,对Object对象数组采用 ...
- java.util.Arrays.sort两种方式的排序(及文件读写练习)
import java.io.*; import java.util.*; public class SortTest{ public static void main(String args[]) ...
- [转]Arrays.sort()你应该知道的事
以下内容转自: 原文链接: programcreek 翻译: ImportNew.com- 刘志军 译文链接: http://www.importnew.com/8952.html --------- ...
- Arrays.sort 与 Collections.sort
代码如下: package com.wangzhu.arrays; import java.util.Arrays; import java.util.Collections; public clas ...
- Arrays.sort源代码解析
Java Arrays.sort源代码解析 Java Arrays中提供了对所有类型的排序.其中主要分为Primitive(8种基本类型)和Object两大类. 基本类型:采用调优的快速排序: 对象类 ...
- HDOJ(HDU) 2093 考试排名(Arrays.sort排序、类的应用)
Problem Description C++编程考试使用的实时提交系统,具有即时获得成绩排名的特点.它的功能是怎么实现的呢? 我们做好了题目的解答,提交之后,要么"AC",要么错 ...
- 深入理解Arrays.sort() (转)
Arrays.sort(T[], Comparator < ? super T > c) 方法用于对象数组按用户自定义规则排序.官方Java文档只是简要描述此方法的作用,并未进行详细的介绍 ...
- 关于Java中Arrays.sort()方法TLE
最近一直在练用Java写题,今天无意发现一道很简单的二分题(链接),我一开始是直接开int[]数组调用Arrays.sort()去排序,没想到TLE了,原来是因为jdk中对于int[]的排序是使用快速 ...
随机推荐
- [转] 使用git自动部署简单网站
要做什么 假设你有一个博客,有一台网站服务器(或者很多台作负载均衡的服务器),当你的博客要升级时,你可能要在你自己的电脑上写好代码(可能包括本地调试好),然后提交到git(或svn),然后在每个服务器 ...
- 什么是php命名空间
php命名空间是在5.3版本后加入的,命名空间反过来就是空间命名,在这里的空间命名就像window下的文件夹命名,命名空间用关键字namespace来定义.在这里用文件夹举三个例子,比如相对于test ...
- 利用html+ashx实现aspx的功能
最近准备学习下ASP.NET,初期在网上看了些视频教程,准备将自己学习的东西整理整理,留着日后可以参考参考. 本文采用了html.ashx实现aspx,实现了一个最简单的动态网页效果,开发环境是VS2 ...
- HashMap HashTable HashSet
原文转载自 http://blog.csdn.net/wl_ldy/article/details/5941770 HashMap是新框架中用来代替HashTable的类 也就是说建议使用HashMa ...
- Jmeter软件测试2--http接口测试
上次利用Jmeter进行了webservice接口的测试,本次利用Jmeter进行http接口的测试 1.新建线程组 2.新建配置文件 3.新建http请求 4.配置动态请求 4.查看测试结果
- LeetCode OJ -Happy Number
题目链接:https://leetcode.com/problems/happy-number/ 题目理解:实现isHappy函数,判断一个正整数是否为happy数 happy数:计算要判断的数的每一 ...
- Visual Studio 2013环境下操作vc6/vc7/vc8等低版本平台项目【编译|生成|调试】
现代化的开发环境,微软一直在推出更新换代,我们所处的技术环境在日新月异的变化:不过在中国多数人们一边疲惫的追赶着时代的步伐,一边坚守着自己所获悉所掌握的那些紧吧吧的知本.对技术工具的掌握并非他们所想要 ...
- window对象细节(转载)
Window对象是客户端javascript最高层对象之一,只要打开浏览器窗口,不管该窗口中是否有打开的网页,当遇到BODY.FRAMESET或FRAME元素时,都会自动建立window对象的实例.另 ...
- 2 - Annotations标注
下面是TestNG标注和参数的一个快速预览 @BeforeSuite 被标注的方法会在这个套件的所有测试执行之前执行 @AfterSuite 被标注的方法会在这个套件的所有测试执行之后执行 @Bef ...
- js对象的复制,传递,新增,删除和比较
当我们把一个某个对象拷贝或者传递给某个函数时,往往传递的是该对象的引用. 因此我们在引用上做的任何改动,都将会影响到它所引用的原对象. 复制,拷贝 var o = { add: 'Changdao ...