White's Studio.

Java的Array.sort涉及的算法运用

2018/08/24 Share

Array.sort涉及的算法运用

问题1:

Java的sort方法用到什么样的排序算法

1.归并排序(数组类型为object对象类型)

2.快速排序 (数组类型为原型数据类型)

辅助的其他几种排序 (数组长度小时)

3.冒泡排序

问题2:

为什么需要用不同种算法结合?

这个涉及到算法的两个复杂度

  1. 时间复杂度——用来检验某个算法处理一定量的数据要花多长时间
  2. 空间复杂度——对一个算法在运行过程中临时占用存储空间大小的量度

归并排序

  • 拆分阶段,将序列分为更小的序列

  • 排序阶段,把小的序列合在一起(使用合并算法)来构成更大的序列

    img

img

代码链接:

优点:它的时间复杂度为O(nlogn),同时是一种稳定性排序,也就是相等的元素在序列中的相对位置在排序前后不会发生变化
缺点:需要利用额外的n的空间来进行排序。

快速排序

把数组根据一个参照值划分为两部分,左边部分小于等于参照值,右边部分大于等于参照值,然后再不断递归调用该方法,直到数组只有一个元素,就认为其是有序的.注意:划分过程,左边部分和右边部分可以是不均衡的

参考文献链接:https://blog.csdn.net/vayne_xiao/article/details/53508973

代码链接:https://blog.csdn.net/m0_38082440/article/details/81125156

优点:一般时间复杂度为nOlog(n),不需要太多额外的空间
缺点:不稳定,且复杂度在最坏的场景会为Olog(n^2)

附:Java 的 Arrays.sort方法源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package com.util;

public class ArraysPrimitive {
private ArraysPrimitive() {}

/**
* 对指定的 int 型数组按数字升序进行排序。
*/
public static void sort(int[] a) {
sort1(a, 0, a.length);
}

/**
* 对指定 int 型数组的指定范围按数字升序进行排序。
*/
public static void sort(int[] a, int fromIndex, int toIndex) {
rangeCheck(a.length, fromIndex, toIndex);
sort1(a, fromIndex, toIndex - fromIndex);
}

private static void sort1(int x[], int off, int len) {
/*
* 当待排序的数组中的元素个数小于 7 时,采用插入排序 。
*
* 尽管插入排序的时间复杂度为O(n^2),但是当数组元素较少时, 插入排序优于快速排序,因为这时快速排序的递归操作影响性能。
*/
if (len < 7) {
for (int i = off; i < len + off; i++)
for (int j = i; j > off && x[j - 1] > x[j]; j--)
swap(x, j, j - 1);
return;
}
/*
* 当待排序的数组中的元素个数大于 或等于7 时,采用快速排序 。
*
* Choose a partition element, v
* 选取一个划分元,V
*
* 较好的选择了划分元(基准元素)。能够将数组分成大致两个相等的部分,避免出现最坏的情况。例如当数组有序的的情况下,
* 选择第一个元素作为划分元,将使得算法的时间复杂度达到O(n^2).
*/
// 当数组大小为size=7时 ,取数组中间元素作为划分元。
int m = off + (len >> 1);
// 当数组大小 7<size<=40时,取首、中、末 三个元素中间大小的元素作为划分元。
if (len > 7) {
int l = off;
int n = off + len - 1;
/*
* 当数组大小 size>40 时 ,从待排数组中较均匀的选择9个元素,
* 选出一个伪中数做为划分元。
*/
if (len > 40) {
int s = len / 8;
l = med3(x, l, l + s, l + 2 * s);
m = med3(x, m - s, m, m + s);
n = med3(x, n - 2 * s, n - s, n);
}
// 取出中间大小的元素的位置。
m = med3(x, l, m, n); // Mid-size, med of 3
}

//得到划分元V
int v = x[m];

// Establish Invariant: v* (<v)* (>v)* v*
int a = off, b = a, c = off + len - 1, d = c;
while (true) {
while (b <= c && x[b] <= v) {
if (x[b] == v)
swap(x, a++, b);
b++;
}
while (c >= b && x[c] >= v) {
if (x[c] == v)
swap(x, c, d--);
c--;
}
if (b > c)
break;
swap(x, b++, c--);
}
// Swap partition elements back to middle
int s, n = off + len;
s = Math.min(a - off, b - a);
vecswap(x, off, b - s, s);
s = Math.min(d - c, n - d - 1);
vecswap(x, b, n - s, s);
// Recursively sort non-partition-elements
if ((s = b - a) > 1)
sort1(x, off, s);
if ((s = d - c) > 1)
sort1(x, n - s, s);
}

/**
* Swaps x[a] with x[b].
*/
private static void swap(int x[], int a, int b) {
int t = x[a];
x[a] = x[b];
x[b] = t;
}

/**
* Swaps x[a .. (a+n-1)] with x[b .. (b+n-1)].
*/
private static void vecswap(int x[], int a, int b, int n) {
for (int i=0; i<n; i++, a++, b++)
swap(x, a, b);
}

/**
* Returns the index of the median of the three indexed integers.
*/
private static int med3(int x[], int a, int b, int c) {
return (x[a] < x[b] ? (x[b] < x[c] ? b : x[a] < x[c] ? c : a)
: (x[b] > x[c] ? b : x[a] > x[c] ? c : a));
}

/**
* Check that fromIndex and toIndex are in range, and throw an
* appropriate exception if they aren't.
*/
private static void rangeCheck(int arrayLen, int fromIndex, int toIndex) {
if (fromIndex > toIndex)
throw new IllegalArgumentException("fromIndex(" + fromIndex
+ ") > toIndex(" + toIndex + ")");
if (fromIndex < 0)
throw new ArrayIndexOutOfBoundsException(fromIndex);
if (toIndex > arrayLen)
throw new ArrayIndexOutOfBoundsException(toIndex);
}
}
CATALOG
  1. 1. Array.sort涉及的算法运用
    1. 1.0.1. 问题1:
      1. 1.0.1.1. Java的sort方法用到什么样的排序算法
    2. 1.0.2. 问题2:
      1. 1.0.2.1. 为什么需要用不同种算法结合?
    3. 1.0.3. 归并排序
      1. 1.0.3.0.1. 优点:它的时间复杂度为O(nlogn),同时是一种稳定性排序,也就是相等的元素在序列中的相对位置在排序前后不会发生变化
      2. 1.0.3.0.2. 缺点:需要利用额外的n的空间来进行排序。
  2. 1.0.4. 快速排序
    1. 1.0.4.0.1. 优点:一般时间复杂度为nOlog(n),不需要太多额外的空间
    2. 1.0.4.0.2. 缺点:不稳定,且复杂度在最坏的场景会为Olog(n^2)