Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
090a9645
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
090a9645
编写于
10月 15, 2010
作者:
A
alanb
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
6976036: Dual-pivot quicksort update (10/2010 tune-up)
Reviewed-by: alanb Contributed-by: vladimir.yaroslavskiy@oracle.com
上级
adff931e
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
963 addition
and
1021 deletion
+963
-1021
src/share/classes/java/util/Arrays.java
src/share/classes/java/util/Arrays.java
+14
-8
src/share/classes/java/util/DualPivotQuicksort.java
src/share/classes/java/util/DualPivotQuicksort.java
+583
-881
test/java/util/Arrays/Sorting.java
test/java/util/Arrays/Sorting.java
+366
-132
未找到文件。
src/share/classes/java/util/Arrays.java
浏览文件 @
090a9645
...
@@ -97,7 +97,8 @@ public class Arrays {
...
@@ -97,7 +97,8 @@ public class Arrays {
* if {@code fromIndex < 0} or {@code toIndex > a.length}
* if {@code fromIndex < 0} or {@code toIndex > a.length}
*/
*/
public
static
void
sort
(
int
[]
a
,
int
fromIndex
,
int
toIndex
)
{
public
static
void
sort
(
int
[]
a
,
int
fromIndex
,
int
toIndex
)
{
DualPivotQuicksort
.
sort
(
a
,
fromIndex
,
toIndex
);
rangeCheck
(
a
.
length
,
fromIndex
,
toIndex
);
DualPivotQuicksort
.
sort
(
a
,
fromIndex
,
toIndex
-
1
);
}
}
/**
/**
...
@@ -136,7 +137,8 @@ public class Arrays {
...
@@ -136,7 +137,8 @@ public class Arrays {
* if {@code fromIndex < 0} or {@code toIndex > a.length}
* if {@code fromIndex < 0} or {@code toIndex > a.length}
*/
*/
public
static
void
sort
(
long
[]
a
,
int
fromIndex
,
int
toIndex
)
{
public
static
void
sort
(
long
[]
a
,
int
fromIndex
,
int
toIndex
)
{
DualPivotQuicksort
.
sort
(
a
,
fromIndex
,
toIndex
);
rangeCheck
(
a
.
length
,
fromIndex
,
toIndex
);
DualPivotQuicksort
.
sort
(
a
,
fromIndex
,
toIndex
-
1
);
}
}
/**
/**
...
@@ -175,7 +177,8 @@ public class Arrays {
...
@@ -175,7 +177,8 @@ public class Arrays {
* if {@code fromIndex < 0} or {@code toIndex > a.length}
* if {@code fromIndex < 0} or {@code toIndex > a.length}
*/
*/
public
static
void
sort
(
short
[]
a
,
int
fromIndex
,
int
toIndex
)
{
public
static
void
sort
(
short
[]
a
,
int
fromIndex
,
int
toIndex
)
{
DualPivotQuicksort
.
sort
(
a
,
fromIndex
,
toIndex
);
rangeCheck
(
a
.
length
,
fromIndex
,
toIndex
);
DualPivotQuicksort
.
sort
(
a
,
fromIndex
,
toIndex
-
1
);
}
}
/**
/**
...
@@ -214,7 +217,8 @@ public class Arrays {
...
@@ -214,7 +217,8 @@ public class Arrays {
* if {@code fromIndex < 0} or {@code toIndex > a.length}
* if {@code fromIndex < 0} or {@code toIndex > a.length}
*/
*/
public
static
void
sort
(
char
[]
a
,
int
fromIndex
,
int
toIndex
)
{
public
static
void
sort
(
char
[]
a
,
int
fromIndex
,
int
toIndex
)
{
DualPivotQuicksort
.
sort
(
a
,
fromIndex
,
toIndex
);
rangeCheck
(
a
.
length
,
fromIndex
,
toIndex
);
DualPivotQuicksort
.
sort
(
a
,
fromIndex
,
toIndex
-
1
);
}
}
/**
/**
...
@@ -253,7 +257,8 @@ public class Arrays {
...
@@ -253,7 +257,8 @@ public class Arrays {
* if {@code fromIndex < 0} or {@code toIndex > a.length}
* if {@code fromIndex < 0} or {@code toIndex > a.length}
*/
*/
public
static
void
sort
(
byte
[]
a
,
int
fromIndex
,
int
toIndex
)
{
public
static
void
sort
(
byte
[]
a
,
int
fromIndex
,
int
toIndex
)
{
DualPivotQuicksort
.
sort
(
a
,
fromIndex
,
toIndex
);
rangeCheck
(
a
.
length
,
fromIndex
,
toIndex
);
DualPivotQuicksort
.
sort
(
a
,
fromIndex
,
toIndex
-
1
);
}
}
/**
/**
...
@@ -308,7 +313,8 @@ public class Arrays {
...
@@ -308,7 +313,8 @@ public class Arrays {
* if {@code fromIndex < 0} or {@code toIndex > a.length}
* if {@code fromIndex < 0} or {@code toIndex > a.length}
*/
*/
public
static
void
sort
(
float
[]
a
,
int
fromIndex
,
int
toIndex
)
{
public
static
void
sort
(
float
[]
a
,
int
fromIndex
,
int
toIndex
)
{
DualPivotQuicksort
.
sort
(
a
,
fromIndex
,
toIndex
);
rangeCheck
(
a
.
length
,
fromIndex
,
toIndex
);
DualPivotQuicksort
.
sort
(
a
,
fromIndex
,
toIndex
-
1
);
}
}
/**
/**
...
@@ -363,12 +369,12 @@ public class Arrays {
...
@@ -363,12 +369,12 @@ public class Arrays {
* if {@code fromIndex < 0} or {@code toIndex > a.length}
* if {@code fromIndex < 0} or {@code toIndex > a.length}
*/
*/
public
static
void
sort
(
double
[]
a
,
int
fromIndex
,
int
toIndex
)
{
public
static
void
sort
(
double
[]
a
,
int
fromIndex
,
int
toIndex
)
{
DualPivotQuicksort
.
sort
(
a
,
fromIndex
,
toIndex
);
rangeCheck
(
a
.
length
,
fromIndex
,
toIndex
);
DualPivotQuicksort
.
sort
(
a
,
fromIndex
,
toIndex
-
1
);
}
}
/*
/*
* Sorting of complex type arrays.
* Sorting of complex type arrays.
*
*/
*/
/**
/**
...
...
src/share/classes/java/util/DualPivotQuicksort.java
浏览文件 @
090a9645
...
@@ -36,7 +36,7 @@ package java.util;
...
@@ -36,7 +36,7 @@ package java.util;
* @author Jon Bentley
* @author Jon Bentley
* @author Josh Bloch
* @author Josh Bloch
*
*
* @version 2010.
06.21 m765.827.12i:5\7
* @version 2010.
10.13 m765.827.12i:5\7p
* @since 1.7
* @since 1.7
*/
*/
final
class
DualPivotQuicksort
{
final
class
DualPivotQuicksort
{
...
@@ -54,26 +54,26 @@ final class DualPivotQuicksort {
...
@@ -54,26 +54,26 @@ final class DualPivotQuicksort {
* If the length of an array to be sorted is less than this
* If the length of an array to be sorted is less than this
* constant, insertion sort is used in preference to Quicksort.
* constant, insertion sort is used in preference to Quicksort.
*/
*/
private
static
final
int
INSERTION_SORT_THRESHOLD
=
32
;
private
static
final
int
INSERTION_SORT_THRESHOLD
=
47
;
/**
/**
* If the length of a byte array to be sorted is greater than
* If the length of a byte array to be sorted is greater than
this
*
this constant, counting sort is used in preference to Quick
sort.
*
constant, counting sort is used in preference to insertion
sort.
*/
*/
private
static
final
int
COUNTING_SORT_THRESHOLD_FOR_BYTE
=
128
;
private
static
final
int
COUNTING_SORT_THRESHOLD_FOR_BYTE
=
29
;
/**
/**
* If the length of a short or char array to be sorted is greater
* If the length of a short or char array to be sorted is greater
* than this constant, counting sort is used in preference to Quicksort.
* than this constant, counting sort is used in preference to Quicksort.
*/
*/
private
static
final
int
COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR
=
32
768
;
private
static
final
int
COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR
=
32
00
;
/*
/*
* Sorting methods for seven primitive types.
* Sorting methods for seven primitive types.
*/
*/
/**
/**
* Sorts the specified array
into ascending numerical order
.
* Sorts the specified array.
*
*
* @param a the array to be sorted
* @param a the array to be sorted
*/
*/
...
@@ -82,58 +82,34 @@ final class DualPivotQuicksort {
...
@@ -82,58 +82,34 @@ final class DualPivotQuicksort {
}
}
/**
/**
* Sorts the specified range of the array into ascending order. The range
* Sorts the specified range of the array.
* to be sorted extends from the index {@code fromIndex}, inclusive, to
* the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the range to be sorted is empty (and the call is a no-op).
*
*
* @param a the array to be sorted
* @param a the array to be sorted
* @param fromIndex the index of the first element, inclusive, to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param toIndex the index of the last element, exclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
* @throws IllegalArgumentException if {@code fromIndex > toIndex}
* @throws ArrayIndexOutOfBoundsException
* if {@code fromIndex < 0} or {@code toIndex > a.length}
*/
*/
public
static
void
sort
(
int
[]
a
,
int
fromIndex
,
int
toIndex
)
{
public
static
void
sort
(
int
[]
a
,
int
left
,
int
right
)
{
rangeCheck
(
a
.
length
,
fromIndex
,
toIndex
);
sort
(
a
,
left
,
right
,
true
);
sort
(
a
,
fromIndex
,
toIndex
-
1
,
true
);
}
}
/**
/**
* Sorts the specified range of the array into ascending order by the
* Sorts the specified range of the array by Dual-Pivot Quicksort.
* Dual-Pivot Quicksort algorithm. This method differs from the public
* {@code sort} method in that the {@code right} index is inclusive,
* it does no range checking on {@code left} or {@code right}, and has
* boolean flag whether insertion sort with sentinel is used or not.
*
*
* @param a the array to be sorted
* @param a the array to be sorted
* @param left the index of the first element, inclusive, 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 right the index of the last element, inclusive, to be sorted
* @param leftmost indicates if th
e part is the most lef
t in the range
* @param leftmost indicates if th
is part is the leftmos
t in the range
*/
*/
private
static
void
sort
(
int
[]
a
,
int
left
,
int
right
,
boolean
leftmost
)
{
private
static
void
sort
(
int
[]
a
,
int
left
,
int
right
,
boolean
leftmost
)
{
int
length
=
right
-
left
+
1
;
int
length
=
right
-
left
+
1
;
// Use insertion sort on
tiny
arrays
// Use insertion sort on
small
arrays
if
(
length
<
INSERTION_SORT_THRESHOLD
)
{
if
(
length
<
INSERTION_SORT_THRESHOLD
)
{
if
(
!
leftmost
)
{
if
(
leftmost
)
{
/*
/*
* Every element in adjoining part plays the role
* Traditional (without sentinel) insertion sort,
* of sentinel, therefore this allows us to avoid
* optimized for server VM, is used in case of
* the j >= left check on each iteration.
* the leftmost part.
*/
for
(
int
j
,
i
=
left
+
1
;
i
<=
right
;
i
++)
{
int
ai
=
a
[
i
];
for
(
j
=
i
-
1
;
ai
<
a
[
j
];
j
--)
{
// assert j >= left;
a
[
j
+
1
]
=
a
[
j
];
}
a
[
j
+
1
]
=
ai
;
}
}
else
{
/*
* For case of leftmost part traditional (without a sentinel)
* insertion sort, optimized for server JVM, is used.
*/
*/
for
(
int
i
=
left
,
j
=
i
;
i
<
right
;
j
=
++
i
)
{
for
(
int
i
=
left
,
j
=
i
;
i
<
right
;
j
=
++
i
)
{
int
ai
=
a
[
i
+
1
];
int
ai
=
a
[
i
+
1
];
...
@@ -145,12 +121,54 @@ final class DualPivotQuicksort {
...
@@ -145,12 +121,54 @@ final class DualPivotQuicksort {
}
}
a
[
j
+
1
]
=
ai
;
a
[
j
+
1
]
=
ai
;
}
}
}
else
{
/*
* Skip the longest ascending sequence.
*/
do
{
if
(
left
++
>=
right
)
{
return
;
}
}
while
(
a
[
left
-
1
]
<=
a
[
left
]);
/*
* 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 best improved algorithm, so called pair insertion
* sort, which is faster than traditional implementation
* in the context of Dual-Pivot Quicksort.
*/
for
(
int
k
=
left
--;
(
left
+=
2
)
<=
right
;
)
{
int
a1
,
a2
;
k
=
left
-
1
;
if
(
a
[
k
]
<
a
[
left
])
{
a2
=
a
[
k
];
a1
=
a
[
left
];
}
else
{
a1
=
a
[
k
];
a2
=
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
;
return
;
}
}
// Inexpensive approximation of length / 7
// Inexpensive approximation of length / 7
int
seventh
=
(
length
>>
>
3
)
+
(
length
>
>>
6
)
+
1
;
int
seventh
=
(
length
>>
3
)
+
(
length
>>
6
)
+
1
;
/*
/*
* Sort five evenly spaced elements around (and including) the
* Sort five evenly spaced elements around (and including) the
...
@@ -232,10 +250,14 @@ final class DualPivotQuicksort {
...
@@ -232,10 +250,14 @@ final class DualPivotQuicksort {
* Pointer k is the first index of ?-part.
* Pointer k is the first index of ?-part.
*/
*/
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++
)
{
for
(
int
k
=
less
-
1
;
++
k
<=
great
;
)
{
int
ak
=
a
[
k
];
int
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
/*
* Here and below we use "a[i] = b; i++;" instead
* of "a[i++] = b;" due to performance issue.
*/
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
less
++;
less
++;
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
...
@@ -244,13 +266,17 @@ final class DualPivotQuicksort {
...
@@ -244,13 +266,17 @@ final class DualPivotQuicksort {
break
outer
;
break
outer
;
}
}
}
}
if
(
a
[
great
]
<
pivot1
)
{
if
(
a
[
great
]
<
pivot1
)
{
// a[great] <= pivot2
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
a
[
great
];
a
[
less
]
=
a
[
great
];
less
++;
less
++;
}
else
{
// pivot1 <= a[great] <= pivot2
}
else
{
// pivot1 <= a[great] <= pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
}
}
/*
* Here and below we use "a[i] = b; i--;" instead
* of "a[i--] = b;" due to performance issue.
*/
a
[
great
]
=
ak
;
a
[
great
]
=
ak
;
great
--;
great
--;
}
}
...
@@ -265,7 +291,7 @@ final class DualPivotQuicksort {
...
@@ -265,7 +291,7 @@ final class DualPivotQuicksort {
sort
(
a
,
great
+
2
,
right
,
false
);
sort
(
a
,
great
+
2
,
right
,
false
);
/*
/*
* If center part is too large (comprises >
5
/7 of the array),
* If center part is too large (comprises >
4
/7 of the array),
* swap internal pivot values to ends.
* swap internal pivot values to ends.
*/
*/
if
(
less
<
e1
&&
e5
<
great
)
{
if
(
less
<
e1
&&
e5
<
great
)
{
...
@@ -299,7 +325,7 @@ final class DualPivotQuicksort {
...
@@ -299,7 +325,7 @@ final class DualPivotQuicksort {
* Pointer k is the first index of ?-part.
* Pointer k is the first index of ?-part.
*/
*/
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++
)
{
for
(
int
k
=
less
-
1
;
++
k
<=
great
;
)
{
int
ak
=
a
[
k
];
int
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
...
@@ -311,7 +337,7 @@ final class DualPivotQuicksort {
...
@@ -311,7 +337,7 @@ final class DualPivotQuicksort {
break
outer
;
break
outer
;
}
}
}
}
if
(
a
[
great
]
==
pivot1
)
{
if
(
a
[
great
]
==
pivot1
)
{
// a[great] < pivot2
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
/*
/*
* Even though a[great] equals to pivot1, the
* Even though a[great] equals to pivot1, the
...
@@ -337,7 +363,7 @@ final class DualPivotQuicksort {
...
@@ -337,7 +363,7 @@ final class DualPivotQuicksort {
}
else
{
// Pivots are equal
}
else
{
// Pivots are equal
/*
/*
* Partition degenerates to the traditional 3-way
* Partition
ing
degenerates to the traditional 3-way
* (or "Dutch National Flag") schema:
* (or "Dutch National Flag") schema:
*
*
* left part center part right part
* left part center part right part
...
@@ -356,28 +382,20 @@ final class DualPivotQuicksort {
...
@@ -356,28 +382,20 @@ final class DualPivotQuicksort {
*
*
* Pointer k is the first index of ?-part.
* Pointer k is the first index of ?-part.
*/
*/
for
(
int
k
=
le
ft
;
k
<=
great
;
k
++
)
{
for
(
int
k
=
le
ss
;
k
<=
great
;
++
k
)
{
if
(
a
[
k
]
==
pivot1
)
{
if
(
a
[
k
]
==
pivot1
)
{
continue
;
continue
;
}
}
int
ak
=
a
[
k
];
int
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
less
++;
less
++;
}
else
{
// a[k] > pivot1 - Move a[k] to right part
}
else
{
// a[k] > pivot1 - Move a[k] to right part
/*
* We know that pivot1 == a[e3] == pivot2. Thus, we know
* that great will still be >= k when the following loop
* terminates, even though we don't test for it explicitly.
* In other words, a[e3] acts as a sentinel for great.
*/
while
(
a
[
great
]
>
pivot1
)
{
while
(
a
[
great
]
>
pivot1
)
{
// assert great > k;
great
--;
great
--;
}
}
if
(
a
[
great
]
<
pivot1
)
{
if
(
a
[
great
]
<
pivot1
)
{
// a[great] <= pivot1
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
a
[
great
];
a
[
less
]
=
a
[
great
];
less
++;
less
++;
...
@@ -397,14 +415,18 @@ final class DualPivotQuicksort {
...
@@ -397,14 +415,18 @@ final class DualPivotQuicksort {
}
}
}
}
// Sort left and right parts recursively
/*
* Sort left and right parts recursively.
* All elements from center part are equal
* and, therefore, already sorted.
*/
sort
(
a
,
left
,
less
-
1
,
leftmost
);
sort
(
a
,
left
,
less
-
1
,
leftmost
);
sort
(
a
,
great
+
1
,
right
,
false
);
sort
(
a
,
great
+
1
,
right
,
false
);
}
}
}
}
/**
/**
* Sorts the specified array
into ascending numerical order
.
* Sorts the specified array.
*
*
* @param a the array to be sorted
* @param a the array to be sorted
*/
*/
...
@@ -413,58 +435,34 @@ final class DualPivotQuicksort {
...
@@ -413,58 +435,34 @@ final class DualPivotQuicksort {
}
}
/**
/**
* Sorts the specified range of the array into ascending order. The range
* Sorts the specified range of the array.
* to be sorted extends from the index {@code fromIndex}, inclusive, to
* the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the range to be sorted is empty (and the call is a no-op).
*
*
* @param a the array to be sorted
* @param a the array to be sorted
* @param fromIndex the index of the first element, inclusive, to be sorted
* @param left the index of the first element, inclusive, to be sorted
* @param toIndex the index of the last element, exclusive, to be sorted
* @param right the index of the last element, inclusive, to be sorted
* @throws IllegalArgumentException if {@code fromIndex > toIndex}
* @throws ArrayIndexOutOfBoundsException
* if {@code fromIndex < 0} or {@code toIndex > a.length}
*/
*/
public
static
void
sort
(
long
[]
a
,
int
fromIndex
,
int
toIndex
)
{
public
static
void
sort
(
long
[]
a
,
int
left
,
int
right
)
{
rangeCheck
(
a
.
length
,
fromIndex
,
toIndex
);
sort
(
a
,
left
,
right
,
true
);
sort
(
a
,
fromIndex
,
toIndex
-
1
,
true
);
}
}
/**
/**
* Sorts the specified range of the array into ascending order by the
* Sorts the specified range of the array by Dual-Pivot Quicksort.
* Dual-Pivot Quicksort algorithm. This method differs from the public
* {@code sort} method in that the {@code right} index is inclusive,
* it does no range checking on {@code left} or {@code right}, and has
* boolean flag whether insertion sort with sentinel is used or not.
*
*
* @param a the array to be sorted
* @param a the array to be sorted
* @param left the index of the first element, inclusive, 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 right the index of the last element, inclusive, to be sorted
* @param leftmost indicates if th
e part is the most lef
t in the range
* @param leftmost indicates if th
is part is the leftmos
t in the range
*/
*/
private
static
void
sort
(
long
[]
a
,
int
left
,
int
right
,
boolean
leftmost
)
{
private
static
void
sort
(
long
[]
a
,
int
left
,
int
right
,
boolean
leftmost
)
{
int
length
=
right
-
left
+
1
;
int
length
=
right
-
left
+
1
;
// Use insertion sort on
tiny
arrays
// Use insertion sort on
small
arrays
if
(
length
<
INSERTION_SORT_THRESHOLD
)
{
if
(
length
<
INSERTION_SORT_THRESHOLD
)
{
if
(!
leftmost
)
{
if
(
leftmost
)
{
/*
* Every element in adjoining part plays the role
* of sentinel, therefore this allows us to avoid
* the j >= left check on each iteration.
*/
for
(
int
j
,
i
=
left
+
1
;
i
<=
right
;
i
++)
{
long
ai
=
a
[
i
];
for
(
j
=
i
-
1
;
ai
<
a
[
j
];
j
--)
{
// assert j >= left;
a
[
j
+
1
]
=
a
[
j
];
}
a
[
j
+
1
]
=
ai
;
}
}
else
{
/*
/*
* For case of leftmost part traditional (without a sentinel)
* Traditional (without sentinel) insertion sort,
* insertion sort, optimized for server JVM, is used.
* optimized for server VM, is used in case of
* the leftmost part.
*/
*/
for
(
int
i
=
left
,
j
=
i
;
i
<
right
;
j
=
++
i
)
{
for
(
int
i
=
left
,
j
=
i
;
i
<
right
;
j
=
++
i
)
{
long
ai
=
a
[
i
+
1
];
long
ai
=
a
[
i
+
1
];
...
@@ -476,381 +474,54 @@ final class DualPivotQuicksort {
...
@@ -476,381 +474,54 @@ final class DualPivotQuicksort {
}
}
a
[
j
+
1
]
=
ai
;
a
[
j
+
1
]
=
ai
;
}
}
}
}
else
{
return
;
}
// Inexpensive approximation of length / 7
int
seventh
=
(
length
>>>
3
)
+
(
length
>>>
6
)
+
1
;
/*
* Sort five evenly spaced elements around (and including) the
* center element in the range. These elements will be used for
* pivot selection as described below. The choice for spacing
* these elements was empirically determined to work well on
* a wide variety of inputs.
*/
int
e3
=
(
left
+
right
)
>>>
1
;
// The midpoint
int
e2
=
e3
-
seventh
;
int
e1
=
e2
-
seventh
;
int
e4
=
e3
+
seventh
;
int
e5
=
e4
+
seventh
;
// Sort these elements using insertion sort
if
(
a
[
e2
]
<
a
[
e1
])
{
long
t
=
a
[
e2
];
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
if
(
a
[
e3
]
<
a
[
e2
])
{
long
t
=
a
[
e3
];
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
}
if
(
a
[
e4
]
<
a
[
e3
])
{
long
t
=
a
[
e4
];
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
}
}
if
(
a
[
e5
]
<
a
[
e4
])
{
long
t
=
a
[
e5
];
a
[
e5
]
=
a
[
e4
];
a
[
e4
]
=
t
;
if
(
t
<
a
[
e3
])
{
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
}
}
}
/*
* Use the second and fourth of the five sorted elements as pivots.
* These values are inexpensive approximations of the first and
* second terciles of the array. Note that pivot1 <= pivot2.
*/
long
pivot1
=
a
[
e2
];
long
pivot2
=
a
[
e4
];
// Pointers
int
less
=
left
;
// The index of the first element of center part
int
great
=
right
;
// The index before the first element of right part
if
(
pivot1
!=
pivot2
)
{
/*
* The first and the last elements to be sorted are moved to the
* locations formerly occupied by the pivots. When partitioning
* is complete, the pivots are swapped back into their final
* positions, and excluded from subsequent sorting.
*/
a
[
e2
]
=
a
[
left
];
a
[
e4
]
=
a
[
right
];
/*
* Skip elements, which are less or greater than pivot values.
*/
while
(
a
[++
less
]
<
pivot1
);
while
(
a
[--
great
]
>
pivot2
);
/*
* Partitioning:
*
* left part center part right part
* +--------------------------------------------------------------+
* | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
* +--------------------------------------------------------------+
* ^ ^ ^
* | | |
* less k great
*
* Invariants:
*
* all in (left, less) < pivot1
* pivot1 <= all in [less, k) <= pivot2
* all in (great, right) > pivot2
*
* Pointer k is the first index of ?-part.
*/
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
long
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
less
++;
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
while
(
a
[
great
]
>
pivot2
)
{
if
(
great
--
==
k
)
{
break
outer
;
}
}
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
]
=
a
[
great
];
less
++;
}
else
{
// pivot1 <= a[great] <= pivot2
a
[
k
]
=
a
[
great
];
}
a
[
great
]
=
ak
;
great
--;
}
}
// Swap pivots into their final positions
a
[
left
]
=
a
[
less
-
1
];
a
[
less
-
1
]
=
pivot1
;
a
[
right
]
=
a
[
great
+
1
];
a
[
great
+
1
]
=
pivot2
;
// Sort left and right parts recursively, excluding known pivots
sort
(
a
,
left
,
less
-
2
,
leftmost
);
sort
(
a
,
great
+
2
,
right
,
false
);
/*
* If center part is too large (comprises > 5/7 of the array),
* swap internal pivot values to ends.
*/
if
(
less
<
e1
&&
e5
<
great
)
{
/*
/*
* Skip
elements, which are equal to pivot values
.
* Skip
the longest ascending sequence
.
*/
*/
while
(
a
[
less
]
==
pivot1
)
{
do
{
less
++;
if
(
left
++
>=
right
)
{
}
return
;
while
(
a
[
great
]
==
pivot2
)
{
}
great
--;
}
while
(
a
[
left
-
1
]
<=
a
[
left
]);
}
/*
/*
* Partitioning:
* Every element from adjoining part plays the role
*
* of sentinel, therefore this allows us to avoid the
* left part center part right part
* left range check on each iteration. Moreover, we use
* +----------------------------------------------------------+
* the best improved algorithm, so called pair insertion
* | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 |
* sort, which is faster than traditional implementation
* +----------------------------------------------------------+
* in the context of Dual-Pivot Quicksort.
* ^ ^ ^
* | | |
* less k great
*
* Invariants:
*
* all in (*, less) == pivot1
* pivot1 < all in [less, k) < pivot2
* all in (great, *) == pivot2
*
* Pointer k is the first index of ?-part.
*/
*/
outer:
for
(
int
k
=
left
--;
(
left
+=
2
)
<=
right
;
)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
long
a1
,
a2
;
k
=
left
-
1
;
long
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
less
++;
}
else
if
(
ak
==
pivot2
)
{
// Move a[k] to right part
while
(
a
[
great
]
==
pivot2
)
{
if
(
great
--
==
k
)
{
break
outer
;
}
}
if
(
a
[
great
]
==
pivot1
)
{
a
[
k
]
=
a
[
less
];
/*
* Even though a[great] equals to pivot1, the
* assignment a[less] = pivot1 may be incorrect,
* if a[great] and pivot1 are floating-point zeros
* of different signs. Therefore in float and
* double sorting methods we have to use more
* accurate assignment a[less] = a[great].
*/
a
[
less
]
=
pivot1
;
less
++;
}
else
{
// pivot1 < a[great] < pivot2
a
[
k
]
=
a
[
great
];
}
a
[
great
]
=
ak
;
great
--;
}
}
}
// Sort center part recursively
if
(
a
[
k
]
<
a
[
left
])
{
sort
(
a
,
less
,
great
,
false
);
a2
=
a
[
k
];
a1
=
a
[
left
];
}
else
{
}
else
{
// Pivots are equal
a1
=
a
[
k
];
a2
=
a
[
left
];
/*
* Partition degenerates to the traditional 3-way
* (or "Dutch National Flag") schema:
*
* left part center part right part
* +-------------------------------------------------+
* | < pivot | == pivot | ? | > pivot |
* +-------------------------------------------------+
* ^ ^ ^
* | | |
* less k great
*
* Invariants:
*
* all in (left, less) < pivot
* all in [less, k) == pivot
* all in (great, right) > pivot
*
* Pointer k is the first index of ?-part.
*/
for
(
int
k
=
left
;
k
<=
great
;
k
++)
{
if
(
a
[
k
]
==
pivot1
)
{
continue
;
}
long
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
less
++;
}
else
{
// a[k] > pivot1 - Move a[k] to right part
/*
* We know that pivot1 == a[e3] == pivot2. Thus, we know
* that great will still be >= k when the following loop
* terminates, even though we don't test for it explicitly.
* In other words, a[e3] acts as a sentinel for great.
*/
while
(
a
[
great
]
>
pivot1
)
{
// assert great > k;
great
--;
}
}
if
(
a
[
great
]
<
pivot1
)
{
while
(
a1
<
a
[--
k
])
{
a
[
k
]
=
a
[
less
];
a
[
k
+
2
]
=
a
[
k
];
a
[
less
]
=
a
[
great
];
less
++;
}
else
{
// a[great] == pivot1
/*
* Even though a[great] equals to pivot1, the
* assignment a[k] = pivot1 may be incorrect,
* if a[great] and pivot1 are floating-point
* zeros of different signs. Therefore in float
* and double sorting methods we have to use
* more accurate assignment a[k] = a[great].
*/
a
[
k
]
=
pivot1
;
}
}
a
[
great
]
=
ak
;
a
[++
k
+
1
]
=
a1
;
great
--;
}
}
// Sort left and right parts recursively
sort
(
a
,
left
,
less
-
1
,
leftmost
);
sort
(
a
,
great
+
1
,
right
,
false
);
}
}
/**
while
(
a2
<
a
[--
k
])
{
* Sorts the specified array into ascending numerical order.
a
[
k
+
1
]
=
a
[
k
];
*
* @param a the array to be sorted
*/
public
static
void
sort
(
short
[]
a
)
{
if
(
a
.
length
>
COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR
)
{
countingSort
(
a
,
0
,
a
.
length
-
1
);
}
else
{
sort
(
a
,
0
,
a
.
length
-
1
,
true
);
}
}
/**
* Sorts the specified range of the array into ascending order. The range
* to be sorted extends from the index {@code fromIndex}, inclusive, to
* the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the range to be sorted is empty (and the call is a no-op).
*
* @param a the array to be sorted
* @param fromIndex the index of the first element, inclusive, to be sorted
* @param toIndex the index of the last element, exclusive, to be sorted
* @throws IllegalArgumentException if {@code fromIndex > toIndex}
* @throws ArrayIndexOutOfBoundsException
* if {@code fromIndex < 0} or {@code toIndex > a.length}
*/
public
static
void
sort
(
short
[]
a
,
int
fromIndex
,
int
toIndex
)
{
rangeCheck
(
a
.
length
,
fromIndex
,
toIndex
);
if
(
toIndex
-
fromIndex
>
COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR
)
{
countingSort
(
a
,
fromIndex
,
toIndex
-
1
);
}
else
{
sort
(
a
,
fromIndex
,
toIndex
-
1
,
true
);
}
}
/** The number of distinct short values. */
private
static
final
int
NUM_SHORT_VALUES
=
1
<<
16
;
/**
* Sorts the specified range of the array by counting sort.
*
* @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
*/
private
static
void
countingSort
(
short
[]
a
,
int
left
,
int
right
)
{
int
[]
count
=
new
int
[
NUM_SHORT_VALUES
];
for
(
int
i
=
left
;
i
<=
right
;
i
++)
{
count
[
a
[
i
]
-
Short
.
MIN_VALUE
]++;
}
for
(
int
i
=
NUM_SHORT_VALUES
-
1
,
k
=
right
;
k
>=
left
;
i
--)
{
while
(
count
[
i
]
==
0
)
{
i
--;
}
short
value
=
(
short
)
(
i
+
Short
.
MIN_VALUE
);
int
s
=
count
[
i
];
do
{
a
[
k
--]
=
value
;
}
while
(--
s
>
0
);
}
}
/**
* Sorts the specified range of the array into ascending order by the
* Dual-Pivot Quicksort algorithm. This method differs from the public
* {@code sort} method in that the {@code right} index is inclusive,
* it does no range checking on {@code left} or {@code right}, and has
* boolean flag whether insertion sort with sentinel is used or not.
*
* @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 the part is the most left in the range
*/
private
static
void
sort
(
short
[]
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
)
{
/*
* Every element in adjoining part plays the role
* of sentinel, therefore this allows us to avoid
* the j >= left check on each iteration.
*/
for
(
int
j
,
i
=
left
+
1
;
i
<=
right
;
i
++)
{
short
ai
=
a
[
i
];
for
(
j
=
i
-
1
;
ai
<
a
[
j
];
j
--)
{
// assert j >= left;
a
[
j
+
1
]
=
a
[
j
];
}
}
a
[
j
+
1
]
=
ai
;
a
[
k
+
1
]
=
a2
;
}
}
}
else
{
long
last
=
a
[
right
];
/*
* For case of leftmost part traditional (without a sentinel)
while
(
last
<
a
[--
right
])
{
* insertion sort, optimized for server JVM, is used.
a
[
right
+
1
]
=
a
[
right
];
*/
for
(
int
i
=
left
,
j
=
i
;
i
<
right
;
j
=
++
i
)
{
short
ai
=
a
[
i
+
1
];
while
(
ai
<
a
[
j
])
{
a
[
j
+
1
]
=
a
[
j
];
if
(
j
--
==
left
)
{
break
;
}
}
a
[
j
+
1
]
=
ai
;
}
}
a
[
right
+
1
]
=
last
;
}
}
return
;
return
;
}
}
// Inexpensive approximation of length / 7
// Inexpensive approximation of length / 7
int
seventh
=
(
length
>>
>
3
)
+
(
length
>
>>
6
)
+
1
;
int
seventh
=
(
length
>>
3
)
+
(
length
>>
6
)
+
1
;
/*
/*
* Sort five evenly spaced elements around (and including) the
* Sort five evenly spaced elements around (and including) the
...
@@ -866,17 +537,17 @@ final class DualPivotQuicksort {
...
@@ -866,17 +537,17 @@ final class DualPivotQuicksort {
int
e5
=
e4
+
seventh
;
int
e5
=
e4
+
seventh
;
// Sort these elements using insertion sort
// Sort these elements using insertion sort
if
(
a
[
e2
]
<
a
[
e1
])
{
short
t
=
a
[
e2
];
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
if
(
a
[
e2
]
<
a
[
e1
])
{
long
t
=
a
[
e2
];
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
if
(
a
[
e3
]
<
a
[
e2
])
{
short
t
=
a
[
e3
];
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
a
[
e3
]
<
a
[
e2
])
{
long
t
=
a
[
e3
];
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
}
}
if
(
a
[
e4
]
<
a
[
e3
])
{
short
t
=
a
[
e4
];
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
if
(
a
[
e4
]
<
a
[
e3
])
{
long
t
=
a
[
e4
];
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
}
}
}
}
if
(
a
[
e5
]
<
a
[
e4
])
{
short
t
=
a
[
e5
];
a
[
e5
]
=
a
[
e4
];
a
[
e4
]
=
t
;
if
(
a
[
e5
]
<
a
[
e4
])
{
long
t
=
a
[
e5
];
a
[
e5
]
=
a
[
e4
];
a
[
e4
]
=
t
;
if
(
t
<
a
[
e3
])
{
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
if
(
t
<
a
[
e3
])
{
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
...
@@ -889,8 +560,8 @@ final class DualPivotQuicksort {
...
@@ -889,8 +560,8 @@ final class DualPivotQuicksort {
* These values are inexpensive approximations of the first and
* These values are inexpensive approximations of the first and
* second terciles of the array. Note that pivot1 <= pivot2.
* second terciles of the array. Note that pivot1 <= pivot2.
*/
*/
short
pivot1
=
a
[
e2
];
long
pivot1
=
a
[
e2
];
short
pivot2
=
a
[
e4
];
long
pivot2
=
a
[
e4
];
// Pointers
// Pointers
int
less
=
left
;
// The index of the first element of center part
int
less
=
left
;
// The index of the first element of center part
...
@@ -932,10 +603,14 @@ final class DualPivotQuicksort {
...
@@ -932,10 +603,14 @@ final class DualPivotQuicksort {
* Pointer k is the first index of ?-part.
* Pointer k is the first index of ?-part.
*/
*/
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++
)
{
for
(
int
k
=
less
-
1
;
++
k
<=
great
;
)
{
short
ak
=
a
[
k
];
long
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
/*
* Here and below we use "a[i] = b; i++;" instead
* of "a[i++] = b;" due to performance issue.
*/
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
less
++;
less
++;
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
...
@@ -944,13 +619,17 @@ final class DualPivotQuicksort {
...
@@ -944,13 +619,17 @@ final class DualPivotQuicksort {
break
outer
;
break
outer
;
}
}
}
}
if
(
a
[
great
]
<
pivot1
)
{
if
(
a
[
great
]
<
pivot1
)
{
// a[great] <= pivot2
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
a
[
great
];
a
[
less
]
=
a
[
great
];
less
++;
less
++;
}
else
{
// pivot1 <= a[great] <= pivot2
}
else
{
// pivot1 <= a[great] <= pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
}
}
/*
* Here and below we use "a[i] = b; i--;" instead
* of "a[i--] = b;" due to performance issue.
*/
a
[
great
]
=
ak
;
a
[
great
]
=
ak
;
great
--;
great
--;
}
}
...
@@ -965,7 +644,7 @@ final class DualPivotQuicksort {
...
@@ -965,7 +644,7 @@ final class DualPivotQuicksort {
sort
(
a
,
great
+
2
,
right
,
false
);
sort
(
a
,
great
+
2
,
right
,
false
);
/*
/*
* If center part is too large (comprises >
5
/7 of the array),
* If center part is too large (comprises >
4
/7 of the array),
* swap internal pivot values to ends.
* swap internal pivot values to ends.
*/
*/
if
(
less
<
e1
&&
e5
<
great
)
{
if
(
less
<
e1
&&
e5
<
great
)
{
...
@@ -999,8 +678,8 @@ final class DualPivotQuicksort {
...
@@ -999,8 +678,8 @@ final class DualPivotQuicksort {
* Pointer k is the first index of ?-part.
* Pointer k is the first index of ?-part.
*/
*/
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++
)
{
for
(
int
k
=
less
-
1
;
++
k
<=
great
;
)
{
short
ak
=
a
[
k
];
long
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
...
@@ -1011,7 +690,7 @@ final class DualPivotQuicksort {
...
@@ -1011,7 +690,7 @@ final class DualPivotQuicksort {
break
outer
;
break
outer
;
}
}
}
}
if
(
a
[
great
]
==
pivot1
)
{
if
(
a
[
great
]
==
pivot1
)
{
// a[great] < pivot2
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
/*
/*
* Even though a[great] equals to pivot1, the
* Even though a[great] equals to pivot1, the
...
@@ -1037,7 +716,7 @@ final class DualPivotQuicksort {
...
@@ -1037,7 +716,7 @@ final class DualPivotQuicksort {
}
else
{
// Pivots are equal
}
else
{
// Pivots are equal
/*
/*
* Partition degenerates to the traditional 3-way
* Partition
ing
degenerates to the traditional 3-way
* (or "Dutch National Flag") schema:
* (or "Dutch National Flag") schema:
*
*
* left part center part right part
* left part center part right part
...
@@ -1056,28 +735,20 @@ final class DualPivotQuicksort {
...
@@ -1056,28 +735,20 @@ final class DualPivotQuicksort {
*
*
* Pointer k is the first index of ?-part.
* Pointer k is the first index of ?-part.
*/
*/
for
(
int
k
=
le
ft
;
k
<=
great
;
k
++
)
{
for
(
int
k
=
le
ss
;
k
<=
great
;
++
k
)
{
if
(
a
[
k
]
==
pivot1
)
{
if
(
a
[
k
]
==
pivot1
)
{
continue
;
continue
;
}
}
short
ak
=
a
[
k
];
long
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
less
++;
less
++;
}
else
{
// a[k] > pivot1 - Move a[k] to right part
}
else
{
// a[k] > pivot1 - Move a[k] to right part
/*
* We know that pivot1 == a[e3] == pivot2. Thus, we know
* that great will still be >= k when the following loop
* terminates, even though we don't test for it explicitly.
* In other words, a[e3] acts as a sentinel for great.
*/
while
(
a
[
great
]
>
pivot1
)
{
while
(
a
[
great
]
>
pivot1
)
{
// assert great > k;
great
--;
great
--;
}
}
if
(
a
[
great
]
<
pivot1
)
{
if
(
a
[
great
]
<
pivot1
)
{
// a[great] <= pivot1
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
a
[
great
];
a
[
less
]
=
a
[
great
];
less
++;
less
++;
...
@@ -1097,115 +768,78 @@ final class DualPivotQuicksort {
...
@@ -1097,115 +768,78 @@ final class DualPivotQuicksort {
}
}
}
}
// Sort left and right parts recursively
/*
* Sort left and right parts recursively.
* All elements from center part are equal
* and, therefore, already sorted.
*/
sort
(
a
,
left
,
less
-
1
,
leftmost
);
sort
(
a
,
left
,
less
-
1
,
leftmost
);
sort
(
a
,
great
+
1
,
right
,
false
);
sort
(
a
,
great
+
1
,
right
,
false
);
}
}
}
}
/**
/**
* Sorts the specified array into ascending numerical order.
* Sorts the specified array.
*
* @param a the array to be sorted
*/
public
static
void
sort
(
char
[]
a
)
{
if
(
a
.
length
>
COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR
)
{
countingSort
(
a
,
0
,
a
.
length
-
1
);
}
else
{
sort
(
a
,
0
,
a
.
length
-
1
,
true
);
}
}
/**
* Sorts the specified range of the array into ascending order. The range
* to be sorted extends from the index {@code fromIndex}, inclusive, to
* the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the range to be sorted is empty (and the call is a no-op).
*
*
* @param a the array to be sorted
* @param a the array to be sorted
* @param fromIndex the index of the first element, inclusive, to be sorted
* @param toIndex the index of the last element, exclusive, to be sorted
* @throws IllegalArgumentException if {@code fromIndex > toIndex}
* @throws ArrayIndexOutOfBoundsException
* if {@code fromIndex < 0} or {@code toIndex > a.length}
*/
*/
public
static
void
sort
(
char
[]
a
,
int
fromIndex
,
int
toIndex
)
{
public
static
void
sort
(
short
[]
a
)
{
rangeCheck
(
a
.
length
,
fromIndex
,
toIndex
);
sort
(
a
,
0
,
a
.
length
-
1
);
if
(
toIndex
-
fromIndex
>
COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR
)
{
countingSort
(
a
,
fromIndex
,
toIndex
-
1
);
}
else
{
sort
(
a
,
fromIndex
,
toIndex
-
1
,
true
);
}
}
}
/** The number of distinct char values. */
private
static
final
int
NUM_CHAR_VALUES
=
1
<<
16
;
/**
/**
* Sorts the specified range of the array
by counting sort
.
* Sorts the specified range of the array.
*
*
* @param a the array to be sorted
* @param a the array to be sorted
* @param left the index of the first element, inclusive, 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 right the index of the last element, inclusive, to be sorted
*/
*/
private
static
void
countingSort
(
char
[]
a
,
int
left
,
int
right
)
{
public
static
void
sort
(
short
[]
a
,
int
left
,
int
right
)
{
int
[]
count
=
new
int
[
NUM_CHAR_VALUES
];
// Use counting sort on large arrays
if
(
right
-
left
>
COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR
)
{
int
[]
count
=
new
int
[
NUM_SHORT_VALUES
];
for
(
int
i
=
left
;
i
<=
right
;
i
++)
{
for
(
int
i
=
left
-
1
;
++
i
<=
right
;
)
{
count
[
a
[
i
]]++;
count
[
a
[
i
]
-
Short
.
MIN_VALUE
]++;
}
for
(
int
i
=
0
,
k
=
left
;
k
<=
right
;
i
++)
{
while
(
count
[
i
]
==
0
)
{
i
++;
}
}
char
value
=
(
char
)
i
;
for
(
int
i
=
NUM_SHORT_VALUES
,
k
=
right
+
1
;
k
>
left
;
)
{
int
s
=
count
[
i
];
while
(
count
[--
i
]
==
0
);
short
value
=
(
short
)
(
i
+
Short
.
MIN_VALUE
);
do
{
int
s
=
count
[
i
];
a
[
k
++]
=
value
;
}
while
(--
s
>
0
);
do
{
a
[--
k
]
=
value
;
}
while
(--
s
>
0
);
}
}
else
{
// Use Dual-Pivot Quicksort on small arrays
sort
(
a
,
left
,
right
,
true
);
}
}
}
}
/** The number of distinct short values. */
private
static
final
int
NUM_SHORT_VALUES
=
1
<<
16
;
/**
/**
* Sorts the specified range of the array into ascending order by the
* Sorts the specified range of the array by Dual-Pivot Quicksort.
* Dual-Pivot Quicksort algorithm. This method differs from the public
* {@code sort} method in that the {@code right} index is inclusive,
* it does no range checking on {@code left} or {@code right}, and has
* boolean flag whether insertion sort with sentinel is used or not.
*
*
* @param a the array to be sorted
* @param a the array to be sorted
* @param left the index of the first element, inclusive, 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 right the index of the last element, inclusive, to be sorted
* @param leftmost indicates if th
e part is the most lef
t in the range
* @param leftmost indicates if th
is part is the leftmos
t in the range
*/
*/
private
static
void
sort
(
char
[]
a
,
int
left
,
int
right
,
boolean
leftmost
)
{
private
static
void
sort
(
short
[]
a
,
int
left
,
int
right
,
boolean
leftmost
)
{
int
length
=
right
-
left
+
1
;
int
length
=
right
-
left
+
1
;
// Use insertion sort on
tiny
arrays
// Use insertion sort on
small
arrays
if
(
length
<
INSERTION_SORT_THRESHOLD
)
{
if
(
length
<
INSERTION_SORT_THRESHOLD
)
{
if
(!
leftmost
)
{
if
(
leftmost
)
{
/*
* Every element in adjoining part plays the role
* of sentinel, therefore this allows us to avoid
* the j >= left check on each iteration.
*/
for
(
int
j
,
i
=
left
+
1
;
i
<=
right
;
i
++)
{
char
ai
=
a
[
i
];
for
(
j
=
i
-
1
;
ai
<
a
[
j
];
j
--)
{
// assert j >= left;
a
[
j
+
1
]
=
a
[
j
];
}
a
[
j
+
1
]
=
ai
;
}
}
else
{
/*
/*
* For case of leftmost part traditional (without a sentinel)
* Traditional (without sentinel) insertion sort,
* insertion sort, optimized for server JVM, is used.
* optimized for server VM, is used in case of
* the leftmost part.
*/
*/
for
(
int
i
=
left
,
j
=
i
;
i
<
right
;
j
=
++
i
)
{
for
(
int
i
=
left
,
j
=
i
;
i
<
right
;
j
=
++
i
)
{
char
ai
=
a
[
i
+
1
];
short
ai
=
a
[
i
+
1
];
while
(
ai
<
a
[
j
])
{
while
(
ai
<
a
[
j
])
{
a
[
j
+
1
]
=
a
[
j
];
a
[
j
+
1
]
=
a
[
j
];
if
(
j
--
==
left
)
{
if
(
j
--
==
left
)
{
...
@@ -1214,12 +848,54 @@ final class DualPivotQuicksort {
...
@@ -1214,12 +848,54 @@ final class DualPivotQuicksort {
}
}
a
[
j
+
1
]
=
ai
;
a
[
j
+
1
]
=
ai
;
}
}
}
else
{
/*
* Skip the longest ascending sequence.
*/
do
{
if
(
left
++
>=
right
)
{
return
;
}
}
while
(
a
[
left
-
1
]
<=
a
[
left
]);
/*
* 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 best improved algorithm, so called pair insertion
* sort, which is faster than traditional implementation
* in the context of Dual-Pivot Quicksort.
*/
for
(
int
k
=
left
--;
(
left
+=
2
)
<=
right
;
)
{
short
a1
,
a2
;
k
=
left
-
1
;
if
(
a
[
k
]
<
a
[
left
])
{
a2
=
a
[
k
];
a1
=
a
[
left
];
}
else
{
a1
=
a
[
k
];
a2
=
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
;
}
short
last
=
a
[
right
];
while
(
last
<
a
[--
right
])
{
a
[
right
+
1
]
=
a
[
right
];
}
a
[
right
+
1
]
=
last
;
}
}
return
;
return
;
}
}
// Inexpensive approximation of length / 7
// Inexpensive approximation of length / 7
int
seventh
=
(
length
>>
>
3
)
+
(
length
>
>>
6
)
+
1
;
int
seventh
=
(
length
>>
3
)
+
(
length
>>
6
)
+
1
;
/*
/*
* Sort five evenly spaced elements around (and including) the
* Sort five evenly spaced elements around (and including) the
...
@@ -1235,17 +911,17 @@ final class DualPivotQuicksort {
...
@@ -1235,17 +911,17 @@ final class DualPivotQuicksort {
int
e5
=
e4
+
seventh
;
int
e5
=
e4
+
seventh
;
// Sort these elements using insertion sort
// Sort these elements using insertion sort
if
(
a
[
e2
]
<
a
[
e1
])
{
char
t
=
a
[
e2
];
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
if
(
a
[
e2
]
<
a
[
e1
])
{
short
t
=
a
[
e2
];
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
if
(
a
[
e3
]
<
a
[
e2
])
{
char
t
=
a
[
e3
];
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
a
[
e3
]
<
a
[
e2
])
{
short
t
=
a
[
e3
];
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
}
}
if
(
a
[
e4
]
<
a
[
e3
])
{
char
t
=
a
[
e4
];
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
if
(
a
[
e4
]
<
a
[
e3
])
{
short
t
=
a
[
e4
];
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
}
}
}
}
if
(
a
[
e5
]
<
a
[
e4
])
{
char
t
=
a
[
e5
];
a
[
e5
]
=
a
[
e4
];
a
[
e4
]
=
t
;
if
(
a
[
e5
]
<
a
[
e4
])
{
short
t
=
a
[
e5
];
a
[
e5
]
=
a
[
e4
];
a
[
e4
]
=
t
;
if
(
t
<
a
[
e3
])
{
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
if
(
t
<
a
[
e3
])
{
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
...
@@ -1258,8 +934,8 @@ final class DualPivotQuicksort {
...
@@ -1258,8 +934,8 @@ final class DualPivotQuicksort {
* These values are inexpensive approximations of the first and
* These values are inexpensive approximations of the first and
* second terciles of the array. Note that pivot1 <= pivot2.
* second terciles of the array. Note that pivot1 <= pivot2.
*/
*/
char
pivot1
=
a
[
e2
];
short
pivot1
=
a
[
e2
];
char
pivot2
=
a
[
e4
];
short
pivot2
=
a
[
e4
];
// Pointers
// Pointers
int
less
=
left
;
// The index of the first element of center part
int
less
=
left
;
// The index of the first element of center part
...
@@ -1301,10 +977,14 @@ final class DualPivotQuicksort {
...
@@ -1301,10 +977,14 @@ final class DualPivotQuicksort {
* Pointer k is the first index of ?-part.
* Pointer k is the first index of ?-part.
*/
*/
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++
)
{
for
(
int
k
=
less
-
1
;
++
k
<=
great
;
)
{
char
ak
=
a
[
k
];
short
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
/*
* Here and below we use "a[i] = b; i++;" instead
* of "a[i++] = b;" due to performance issue.
*/
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
less
++;
less
++;
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
...
@@ -1313,13 +993,17 @@ final class DualPivotQuicksort {
...
@@ -1313,13 +993,17 @@ final class DualPivotQuicksort {
break
outer
;
break
outer
;
}
}
}
}
if
(
a
[
great
]
<
pivot1
)
{
if
(
a
[
great
]
<
pivot1
)
{
// a[great] <= pivot2
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
a
[
great
];
a
[
less
]
=
a
[
great
];
less
++;
less
++;
}
else
{
// pivot1 <= a[great] <= pivot2
}
else
{
// pivot1 <= a[great] <= pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
}
}
/*
* Here and below we use "a[i] = b; i--;" instead
* of "a[i--] = b;" due to performance issue.
*/
a
[
great
]
=
ak
;
a
[
great
]
=
ak
;
great
--;
great
--;
}
}
...
@@ -1334,7 +1018,7 @@ final class DualPivotQuicksort {
...
@@ -1334,7 +1018,7 @@ final class DualPivotQuicksort {
sort
(
a
,
great
+
2
,
right
,
false
);
sort
(
a
,
great
+
2
,
right
,
false
);
/*
/*
* If center part is too large (comprises >
5
/7 of the array),
* If center part is too large (comprises >
4
/7 of the array),
* swap internal pivot values to ends.
* swap internal pivot values to ends.
*/
*/
if
(
less
<
e1
&&
e5
<
great
)
{
if
(
less
<
e1
&&
e5
<
great
)
{
...
@@ -1368,8 +1052,8 @@ final class DualPivotQuicksort {
...
@@ -1368,8 +1052,8 @@ final class DualPivotQuicksort {
* Pointer k is the first index of ?-part.
* Pointer k is the first index of ?-part.
*/
*/
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++
)
{
for
(
int
k
=
less
-
1
;
++
k
<=
great
;
)
{
char
ak
=
a
[
k
];
short
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
...
@@ -1380,7 +1064,7 @@ final class DualPivotQuicksort {
...
@@ -1380,7 +1064,7 @@ final class DualPivotQuicksort {
break
outer
;
break
outer
;
}
}
}
}
if
(
a
[
great
]
==
pivot1
)
{
if
(
a
[
great
]
==
pivot1
)
{
// a[great] < pivot2
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
/*
/*
* Even though a[great] equals to pivot1, the
* Even though a[great] equals to pivot1, the
...
@@ -1406,7 +1090,7 @@ final class DualPivotQuicksort {
...
@@ -1406,7 +1090,7 @@ final class DualPivotQuicksort {
}
else
{
// Pivots are equal
}
else
{
// Pivots are equal
/*
/*
* Partition degenerates to the traditional 3-way
* Partition
ing
degenerates to the traditional 3-way
* (or "Dutch National Flag") schema:
* (or "Dutch National Flag") schema:
*
*
* left part center part right part
* left part center part right part
...
@@ -1425,28 +1109,20 @@ final class DualPivotQuicksort {
...
@@ -1425,28 +1109,20 @@ final class DualPivotQuicksort {
*
*
* Pointer k is the first index of ?-part.
* Pointer k is the first index of ?-part.
*/
*/
for
(
int
k
=
le
ft
;
k
<=
great
;
k
++
)
{
for
(
int
k
=
le
ss
;
k
<=
great
;
++
k
)
{
if
(
a
[
k
]
==
pivot1
)
{
if
(
a
[
k
]
==
pivot1
)
{
continue
;
continue
;
}
}
char
ak
=
a
[
k
];
short
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
less
++;
less
++;
}
else
{
// a[k] > pivot1 - Move a[k] to right part
}
else
{
// a[k] > pivot1 - Move a[k] to right part
/*
* We know that pivot1 == a[e3] == pivot2. Thus, we know
* that great will still be >= k when the following loop
* terminates, even though we don't test for it explicitly.
* In other words, a[e3] acts as a sentinel for great.
*/
while
(
a
[
great
]
>
pivot1
)
{
while
(
a
[
great
]
>
pivot1
)
{
// assert great > k;
great
--;
great
--;
}
}
if
(
a
[
great
]
<
pivot1
)
{
if
(
a
[
great
]
<
pivot1
)
{
// a[great] <= pivot1
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
a
[
great
];
a
[
less
]
=
a
[
great
];
less
++;
less
++;
...
@@ -1466,115 +1142,78 @@ final class DualPivotQuicksort {
...
@@ -1466,115 +1142,78 @@ final class DualPivotQuicksort {
}
}
}
}
// Sort left and right parts recursively
/*
* Sort left and right parts recursively.
* All elements from center part are equal
* and, therefore, already sorted.
*/
sort
(
a
,
left
,
less
-
1
,
leftmost
);
sort
(
a
,
left
,
less
-
1
,
leftmost
);
sort
(
a
,
great
+
1
,
right
,
false
);
sort
(
a
,
great
+
1
,
right
,
false
);
}
}
}
}
/**
/**
* Sorts the specified array
into ascending numerical order
.
* Sorts the specified array.
*
*
* @param a the array to be sorted
* @param a the array to be sorted
*/
*/
public
static
void
sort
(
byte
[]
a
)
{
public
static
void
sort
(
char
[]
a
)
{
if
(
a
.
length
>
COUNTING_SORT_THRESHOLD_FOR_BYTE
)
{
sort
(
a
,
0
,
a
.
length
-
1
);
countingSort
(
a
,
0
,
a
.
length
-
1
);
}
else
{
sort
(
a
,
0
,
a
.
length
-
1
,
true
);
}
}
/**
* Sorts the specified range of the array into ascending order. The range
* to be sorted extends from the index {@code fromIndex}, inclusive, to
* the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the range to be sorted is empty (and the call is a no-op).
*
* @param a the array to be sorted
* @param fromIndex the index of the first element, inclusive, to be sorted
* @param toIndex the index of the last element, exclusive, to be sorted
* @throws IllegalArgumentException if {@code fromIndex > toIndex}
* @throws ArrayIndexOutOfBoundsException
* if {@code fromIndex < 0} or {@code toIndex > a.length}
*/
public
static
void
sort
(
byte
[]
a
,
int
fromIndex
,
int
toIndex
)
{
rangeCheck
(
a
.
length
,
fromIndex
,
toIndex
);
if
(
toIndex
-
fromIndex
>
COUNTING_SORT_THRESHOLD_FOR_BYTE
)
{
countingSort
(
a
,
fromIndex
,
toIndex
-
1
);
}
else
{
sort
(
a
,
fromIndex
,
toIndex
-
1
,
true
);
}
}
}
/** The number of distinct byte values. */
private
static
final
int
NUM_BYTE_VALUES
=
1
<<
8
;
/**
/**
* Sorts the specified range of the array
by counting sort
.
* Sorts the specified range of the array.
*
*
* @param a the array to be sorted
* @param a the array to be sorted
* @param left the index of the first element, inclusive, 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 right the index of the last element, inclusive, to be sorted
*/
*/
private
static
void
countingSort
(
byte
[]
a
,
int
left
,
int
right
)
{
public
static
void
sort
(
char
[]
a
,
int
left
,
int
right
)
{
int
[]
count
=
new
int
[
NUM_BYTE_VALUES
];
// Use counting sort on large arrays
if
(
right
-
left
>
COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR
)
{
int
[]
count
=
new
int
[
NUM_CHAR_VALUES
];
for
(
int
i
=
left
;
i
<=
right
;
i
++)
{
for
(
int
i
=
left
-
1
;
++
i
<=
right
;
)
{
count
[
a
[
i
]
-
Byte
.
MIN_VALUE
]++;
count
[
a
[
i
]]++;
}
for
(
int
i
=
NUM_BYTE_VALUES
-
1
,
k
=
right
;
k
>=
left
;
i
--)
{
while
(
count
[
i
]
==
0
)
{
i
--;
}
}
byte
value
=
(
byte
)
(
i
+
Byte
.
MIN_VALUE
);
for
(
int
i
=
NUM_CHAR_VALUES
,
k
=
right
+
1
;
k
>
left
;
)
{
int
s
=
count
[
i
];
while
(
count
[--
i
]
==
0
);
char
value
=
(
char
)
i
;
do
{
int
s
=
count
[
i
];
a
[
k
--]
=
value
;
}
while
(--
s
>
0
);
do
{
a
[--
k
]
=
value
;
}
while
(--
s
>
0
);
}
}
else
{
// Use Dual-Pivot Quicksort on small arrays
sort
(
a
,
left
,
right
,
true
);
}
}
}
}
/** The number of distinct char values. */
private
static
final
int
NUM_CHAR_VALUES
=
1
<<
16
;
/**
/**
* Sorts the specified range of the array into ascending order by the
* Sorts the specified range of the array by Dual-Pivot Quicksort.
* Dual-Pivot Quicksort algorithm. This method differs from the public
* {@code sort} method in that the {@code right} index is inclusive,
* it does no range checking on {@code left} or {@code right}, and has
* boolean flag whether insertion sort with sentinel is used or not.
*
*
* @param a the array to be sorted
* @param a the array to be sorted
* @param left the index of the first element, inclusive, 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 right the index of the last element, inclusive, to be sorted
* @param leftmost indicates if th
e part is the most lef
t in the range
* @param leftmost indicates if th
is part is the leftmos
t in the range
*/
*/
private
static
void
sort
(
byte
[]
a
,
int
left
,
int
right
,
boolean
leftmost
)
{
private
static
void
sort
(
char
[]
a
,
int
left
,
int
right
,
boolean
leftmost
)
{
int
length
=
right
-
left
+
1
;
int
length
=
right
-
left
+
1
;
// Use insertion sort on
tiny
arrays
// Use insertion sort on
small
arrays
if
(
length
<
INSERTION_SORT_THRESHOLD
)
{
if
(
length
<
INSERTION_SORT_THRESHOLD
)
{
if
(!
leftmost
)
{
if
(
leftmost
)
{
/*
* Every element in adjoining part plays the role
* of sentinel, therefore this allows us to avoid
* the j >= left check on each iteration.
*/
for
(
int
j
,
i
=
left
+
1
;
i
<=
right
;
i
++)
{
byte
ai
=
a
[
i
];
for
(
j
=
i
-
1
;
ai
<
a
[
j
];
j
--)
{
// assert j >= left;
a
[
j
+
1
]
=
a
[
j
];
}
a
[
j
+
1
]
=
ai
;
}
}
else
{
/*
/*
* For case of leftmost part traditional (without a sentinel)
* Traditional (without sentinel) insertion sort,
* insertion sort, optimized for server JVM, is used.
* optimized for server VM, is used in case of
* the leftmost part.
*/
*/
for
(
int
i
=
left
,
j
=
i
;
i
<
right
;
j
=
++
i
)
{
for
(
int
i
=
left
,
j
=
i
;
i
<
right
;
j
=
++
i
)
{
byte
ai
=
a
[
i
+
1
];
char
ai
=
a
[
i
+
1
];
while
(
ai
<
a
[
j
])
{
while
(
ai
<
a
[
j
])
{
a
[
j
+
1
]
=
a
[
j
];
a
[
j
+
1
]
=
a
[
j
];
if
(
j
--
==
left
)
{
if
(
j
--
==
left
)
{
...
@@ -1583,12 +1222,54 @@ final class DualPivotQuicksort {
...
@@ -1583,12 +1222,54 @@ final class DualPivotQuicksort {
}
}
a
[
j
+
1
]
=
ai
;
a
[
j
+
1
]
=
ai
;
}
}
}
else
{
/*
* Skip the longest ascending sequence.
*/
do
{
if
(
left
++
>=
right
)
{
return
;
}
}
while
(
a
[
left
-
1
]
<=
a
[
left
]);
/*
* 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 best improved algorithm, so called pair insertion
* sort, which is faster than traditional implementation
* in the context of Dual-Pivot Quicksort.
*/
for
(
int
k
=
left
--;
(
left
+=
2
)
<=
right
;
)
{
char
a1
,
a2
;
k
=
left
-
1
;
if
(
a
[
k
]
<
a
[
left
])
{
a2
=
a
[
k
];
a1
=
a
[
left
];
}
else
{
a1
=
a
[
k
];
a2
=
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
;
}
char
last
=
a
[
right
];
while
(
last
<
a
[--
right
])
{
a
[
right
+
1
]
=
a
[
right
];
}
a
[
right
+
1
]
=
last
;
}
}
return
;
return
;
}
}
// Inexpensive approximation of length / 7
// Inexpensive approximation of length / 7
int
seventh
=
(
length
>>
>
3
)
+
(
length
>
>>
6
)
+
1
;
int
seventh
=
(
length
>>
3
)
+
(
length
>>
6
)
+
1
;
/*
/*
* Sort five evenly spaced elements around (and including) the
* Sort five evenly spaced elements around (and including) the
...
@@ -1604,17 +1285,17 @@ final class DualPivotQuicksort {
...
@@ -1604,17 +1285,17 @@ final class DualPivotQuicksort {
int
e5
=
e4
+
seventh
;
int
e5
=
e4
+
seventh
;
// Sort these elements using insertion sort
// Sort these elements using insertion sort
if
(
a
[
e2
]
<
a
[
e1
])
{
byte
t
=
a
[
e2
];
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
if
(
a
[
e2
]
<
a
[
e1
])
{
char
t
=
a
[
e2
];
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
if
(
a
[
e3
]
<
a
[
e2
])
{
byte
t
=
a
[
e3
];
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
a
[
e3
]
<
a
[
e2
])
{
char
t
=
a
[
e3
];
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
}
}
if
(
a
[
e4
]
<
a
[
e3
])
{
byte
t
=
a
[
e4
];
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
if
(
a
[
e4
]
<
a
[
e3
])
{
char
t
=
a
[
e4
];
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
}
}
}
}
if
(
a
[
e5
]
<
a
[
e4
])
{
byte
t
=
a
[
e5
];
a
[
e5
]
=
a
[
e4
];
a
[
e4
]
=
t
;
if
(
a
[
e5
]
<
a
[
e4
])
{
char
t
=
a
[
e5
];
a
[
e5
]
=
a
[
e4
];
a
[
e4
]
=
t
;
if
(
t
<
a
[
e3
])
{
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
if
(
t
<
a
[
e3
])
{
a
[
e4
]
=
a
[
e3
];
a
[
e3
]
=
t
;
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e2
])
{
a
[
e3
]
=
a
[
e2
];
a
[
e2
]
=
t
;
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
if
(
t
<
a
[
e1
])
{
a
[
e2
]
=
a
[
e1
];
a
[
e1
]
=
t
;
}
...
@@ -1627,8 +1308,8 @@ final class DualPivotQuicksort {
...
@@ -1627,8 +1308,8 @@ final class DualPivotQuicksort {
* These values are inexpensive approximations of the first and
* These values are inexpensive approximations of the first and
* second terciles of the array. Note that pivot1 <= pivot2.
* second terciles of the array. Note that pivot1 <= pivot2.
*/
*/
byte
pivot1
=
a
[
e2
];
char
pivot1
=
a
[
e2
];
byte
pivot2
=
a
[
e4
];
char
pivot2
=
a
[
e4
];
// Pointers
// Pointers
int
less
=
left
;
// The index of the first element of center part
int
less
=
left
;
// The index of the first element of center part
...
@@ -1670,10 +1351,14 @@ final class DualPivotQuicksort {
...
@@ -1670,10 +1351,14 @@ final class DualPivotQuicksort {
* Pointer k is the first index of ?-part.
* Pointer k is the first index of ?-part.
*/
*/
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++
)
{
for
(
int
k
=
less
-
1
;
++
k
<=
great
;
)
{
byte
ak
=
a
[
k
];
char
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
/*
* Here and below we use "a[i] = b; i++;" instead
* of "a[i++] = b;" due to performance issue.
*/
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
less
++;
less
++;
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
...
@@ -1682,13 +1367,17 @@ final class DualPivotQuicksort {
...
@@ -1682,13 +1367,17 @@ final class DualPivotQuicksort {
break
outer
;
break
outer
;
}
}
}
}
if
(
a
[
great
]
<
pivot1
)
{
if
(
a
[
great
]
<
pivot1
)
{
// a[great] <= pivot2
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
a
[
great
];
a
[
less
]
=
a
[
great
];
less
++;
less
++;
}
else
{
// pivot1 <= a[great] <= pivot2
}
else
{
// pivot1 <= a[great] <= pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
}
}
/*
* Here and below we use "a[i] = b; i--;" instead
* of "a[i--] = b;" due to performance issue.
*/
a
[
great
]
=
ak
;
a
[
great
]
=
ak
;
great
--;
great
--;
}
}
...
@@ -1703,7 +1392,7 @@ final class DualPivotQuicksort {
...
@@ -1703,7 +1392,7 @@ final class DualPivotQuicksort {
sort
(
a
,
great
+
2
,
right
,
false
);
sort
(
a
,
great
+
2
,
right
,
false
);
/*
/*
* If center part is too large (comprises >
5
/7 of the array),
* If center part is too large (comprises >
4
/7 of the array),
* swap internal pivot values to ends.
* swap internal pivot values to ends.
*/
*/
if
(
less
<
e1
&&
e5
<
great
)
{
if
(
less
<
e1
&&
e5
<
great
)
{
...
@@ -1737,8 +1426,8 @@ final class DualPivotQuicksort {
...
@@ -1737,8 +1426,8 @@ final class DualPivotQuicksort {
* Pointer k is the first index of ?-part.
* Pointer k is the first index of ?-part.
*/
*/
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++
)
{
for
(
int
k
=
less
-
1
;
++
k
<=
great
;
)
{
byte
ak
=
a
[
k
];
char
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
...
@@ -1749,7 +1438,7 @@ final class DualPivotQuicksort {
...
@@ -1749,7 +1438,7 @@ final class DualPivotQuicksort {
break
outer
;
break
outer
;
}
}
}
}
if
(
a
[
great
]
==
pivot1
)
{
if
(
a
[
great
]
==
pivot1
)
{
// a[great] < pivot2
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
/*
/*
* Even though a[great] equals to pivot1, the
* Even though a[great] equals to pivot1, the
...
@@ -1775,7 +1464,7 @@ final class DualPivotQuicksort {
...
@@ -1775,7 +1464,7 @@ final class DualPivotQuicksort {
}
else
{
// Pivots are equal
}
else
{
// Pivots are equal
/*
/*
* Partition degenerates to the traditional 3-way
* Partition
ing
degenerates to the traditional 3-way
* (or "Dutch National Flag") schema:
* (or "Dutch National Flag") schema:
*
*
* left part center part right part
* left part center part right part
...
@@ -1794,28 +1483,20 @@ final class DualPivotQuicksort {
...
@@ -1794,28 +1483,20 @@ final class DualPivotQuicksort {
*
*
* Pointer k is the first index of ?-part.
* Pointer k is the first index of ?-part.
*/
*/
for
(
int
k
=
le
ft
;
k
<=
great
;
k
++
)
{
for
(
int
k
=
le
ss
;
k
<=
great
;
++
k
)
{
if
(
a
[
k
]
==
pivot1
)
{
if
(
a
[
k
]
==
pivot1
)
{
continue
;
continue
;
}
}
byte
ak
=
a
[
k
];
char
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
less
++;
less
++;
}
else
{
// a[k] > pivot1 - Move a[k] to right part
}
else
{
// a[k] > pivot1 - Move a[k] to right part
/*
* We know that pivot1 == a[e3] == pivot2. Thus, we know
* that great will still be >= k when the following loop
* terminates, even though we don't test for it explicitly.
* In other words, a[e3] acts as a sentinel for great.
*/
while
(
a
[
great
]
>
pivot1
)
{
while
(
a
[
great
]
>
pivot1
)
{
// assert great > k;
great
--;
great
--;
}
}
if
(
a
[
great
]
<
pivot1
)
{
if
(
a
[
great
]
<
pivot1
)
{
// a[great] <= pivot1
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
a
[
great
];
a
[
less
]
=
a
[
great
];
less
++;
less
++;
...
@@ -1835,73 +1516,90 @@ final class DualPivotQuicksort {
...
@@ -1835,73 +1516,90 @@ final class DualPivotQuicksort {
}
}
}
}
// Sort left and right parts recursively
/*
* Sort left and right parts recursively.
* All elements from center part are equal
* and, therefore, already sorted.
*/
sort
(
a
,
left
,
less
-
1
,
leftmost
);
sort
(
a
,
left
,
less
-
1
,
leftmost
);
sort
(
a
,
great
+
1
,
right
,
false
);
sort
(
a
,
great
+
1
,
right
,
false
);
}
}
}
}
/** The number of distinct byte values. */
private
static
final
int
NUM_BYTE_VALUES
=
1
<<
8
;
/**
/**
* Sorts the specified array into ascending numerical order.
* Sorts the specified array.
*
* <p>The {@code <} relation does not provide a total order on all float
* values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
* value compares neither less than, greater than, nor equal to any value,
* even itself. This method uses the total order imposed by the method
* {@link Float#compareTo}: {@code -0.0f} is treated as less than value
* {@code 0.0f} and {@code Float.NaN} is considered greater than any
* other value and all {@code Float.NaN} values are considered equal.
*
*
* @param a the array to be sorted
* @param a the array to be sorted
*/
*/
public
static
void
sort
(
float
[]
a
)
{
public
static
void
sort
(
byte
[]
a
)
{
sort
NegZeroAndNaN
(
a
,
0
,
a
.
length
-
1
);
sort
(
a
,
0
,
a
.
length
-
1
);
}
}
/**
/**
* Sorts the specified range of the array into ascending order. The range
* Sorts the specified range of the array.
* to be sorted extends from the index {@code fromIndex}, inclusive, to
* the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the range to be sorted is empty (and the call is a no-op).
*
*
* <p>The {@code <} relation does not provide a total order on all float
* @param a the array to be sorted
* values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
* @param left the index of the first element, inclusive, to be sorted
* value compares neither less than, greater than, nor equal to any value,
* @param right the index of the last element, inclusive, to be sorted
* even itself. This method uses the total order imposed by the method
*/
* {@link Float#compareTo}: {@code -0.0f} is treated as less than value
public
static
void
sort
(
byte
[]
a
,
int
left
,
int
right
)
{
* {@code 0.0f} and {@code Float.NaN} is considered greater than any
// Use counting sort on large arrays
* other value and all {@code Float.NaN} values are considered equal.
if
(
right
-
left
>
COUNTING_SORT_THRESHOLD_FOR_BYTE
)
{
int
[]
count
=
new
int
[
NUM_BYTE_VALUES
];
for
(
int
i
=
left
-
1
;
++
i
<=
right
;
)
{
count
[
a
[
i
]
-
Byte
.
MIN_VALUE
]++;
}
for
(
int
i
=
NUM_BYTE_VALUES
,
k
=
right
+
1
;
k
>
left
;
)
{
while
(
count
[--
i
]
==
0
);
byte
value
=
(
byte
)
(
i
+
Byte
.
MIN_VALUE
);
int
s
=
count
[
i
];
do
{
a
[--
k
]
=
value
;
}
while
(--
s
>
0
);
}
}
else
{
// Use insertion sort on small arrays
for
(
int
i
=
left
,
j
=
i
;
i
<
right
;
j
=
++
i
)
{
byte
ai
=
a
[
i
+
1
];
while
(
ai
<
a
[
j
])
{
a
[
j
+
1
]
=
a
[
j
];
if
(
j
--
==
left
)
{
break
;
}
}
a
[
j
+
1
]
=
ai
;
}
}
}
/**
* Sorts the specified array.
*
*
* @param a the array to be sorted
* @param a the array to be sorted
* @param fromIndex the index of the first element, inclusive, to be sorted
* @param toIndex the index of the last element, exclusive, to be sorted
* @throws IllegalArgumentException if {@code fromIndex > toIndex}
* @throws ArrayIndexOutOfBoundsException
* if {@code fromIndex < 0} or {@code toIndex > a.length}
*/
*/
public
static
void
sort
(
float
[]
a
,
int
fromIndex
,
int
toIndex
)
{
public
static
void
sort
(
float
[]
a
)
{
rangeCheck
(
a
.
length
,
fromIndex
,
toIndex
);
sort
(
a
,
0
,
a
.
length
-
1
);
sortNegZeroAndNaN
(
a
,
fromIndex
,
toIndex
-
1
);
}
}
/**
/**
* Sorts the specified range of the array into ascending order. The
* Sorts the specified range of the array.
* sort is done in three phases to avoid expensive comparisons in the
* inner loop. The comparisons would be expensive due to anomalies
* associated with negative zero {@code -0.0f} and {@code Float.NaN}.
*
*
* @param a the array to be sorted
* @param a the array to be sorted
* @param left the index of the first element, inclusive, 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 right the index of the last element, inclusive, to be sorted
*/
*/
p
rivate
static
void
sortNegZeroAndNaN
(
float
[]
a
,
int
left
,
int
right
)
{
p
ublic
static
void
sort
(
float
[]
a
,
int
left
,
int
right
)
{
/*
/*
* Phase 1: Move NaNs to the end of the array.
* Phase 1: Move NaNs to the end of the array.
*/
*/
while
(
left
<=
right
&&
Float
.
isNaN
(
a
[
right
]))
{
while
(
left
<=
right
&&
Float
.
isNaN
(
a
[
right
]))
{
right
--;
right
--;
}
}
for
(
int
k
=
right
-
1
;
k
>=
left
;
k
--
)
{
for
(
int
k
=
right
;
--
k
>=
left
;
)
{
float
ak
=
a
[
k
];
float
ak
=
a
[
k
];
if
(
ak
!=
ak
)
{
// a[k] is NaN
if
(
ak
!=
ak
)
{
// a[k] is NaN
a
[
k
]
=
a
[
right
];
a
[
k
]
=
a
[
right
];
...
@@ -1921,7 +1619,7 @@ final class DualPivotQuicksort {
...
@@ -1921,7 +1619,7 @@ final class DualPivotQuicksort {
int
hi
=
right
;
int
hi
=
right
;
/*
/*
*
Search
first zero, or first positive, or last negative element.
*
Find the
first zero, or first positive, or last negative element.
*/
*/
while
(
left
<
hi
)
{
while
(
left
<
hi
)
{
int
middle
=
(
left
+
hi
)
>>>
1
;
int
middle
=
(
left
+
hi
)
>>>
1
;
...
@@ -1946,12 +1644,12 @@ final class DualPivotQuicksort {
...
@@ -1946,12 +1644,12 @@ final class DualPivotQuicksort {
*
*
* Partitioning:
* Partitioning:
*
*
* +---------------------------------------------------+
* +---------------------------------------------------
-
+
* | < 0.0 | -0.0 |
0.0 | ? ( >= 0.0 )
|
* | < 0.0 | -0.0 |
0.0 | ? ( >= 0.0 )
|
* +---------------------------------------------------+
* +---------------------------------------------------
-
+
* ^ ^
^
* ^ ^ ^
* | |
|
* | | |
* left p
k
* left p k
*
*
* Invariants:
* Invariants:
*
*
...
@@ -1962,53 +1660,36 @@ final class DualPivotQuicksort {
...
@@ -1962,53 +1660,36 @@ final class DualPivotQuicksort {
*
*
* Pointer k is the first index of ?-part.
* Pointer k is the first index of ?-part.
*/
*/
for
(
int
k
=
left
+
1
,
p
=
left
;
k
<=
right
;
k
++
)
{
for
(
int
k
=
left
,
p
=
left
-
1
;
++
k
<=
right
;
)
{
float
ak
=
a
[
k
];
float
ak
=
a
[
k
];
if
(
ak
!=
0.0f
)
{
if
(
ak
!=
0.0f
)
{
break
;
break
;
}
}
if
(
Float
.
floatToRawIntBits
(
ak
)
<
0
)
{
// ak is -0.0f
if
(
Float
.
floatToRawIntBits
(
ak
)
<
0
)
{
// ak is -0.0f
a
[
k
]
=
0.0f
;
a
[
k
]
=
0.0f
;
a
[
p
++
]
=
-
0.0f
;
a
[
++
p
]
=
-
0.0f
;
}
}
}
}
}
}
/**
/**
* Sorts the specified range of the array into ascending order by the
* Sorts the specified range of the array by Dual-Pivot Quicksort.
* Dual-Pivot Quicksort algorithm. This method differs from the public
* {@code sort} method in that the {@code right} index is inclusive,
* it does no range checking on {@code left} or {@code right}, and has
* boolean flag whether insertion sort with sentinel is used or not.
*
*
* @param a the array to be sorted
* @param a the array to be sorted
* @param left the index of the first element, inclusive, 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 right the index of the last element, inclusive, to be sorted
* @param leftmost indicates if th
e part is the most lef
t in the range
* @param leftmost indicates if th
is part is the leftmos
t in the range
*/
*/
private
static
void
sort
(
float
[]
a
,
int
left
,
int
right
,
boolean
leftmost
)
{
private
static
void
sort
(
float
[]
a
,
int
left
,
int
right
,
boolean
leftmost
)
{
int
length
=
right
-
left
+
1
;
int
length
=
right
-
left
+
1
;
// Use insertion sort on
tiny
arrays
// Use insertion sort on
small
arrays
if
(
length
<
INSERTION_SORT_THRESHOLD
)
{
if
(
length
<
INSERTION_SORT_THRESHOLD
)
{
if
(!
leftmost
)
{
if
(
leftmost
)
{
/*
* Every element in adjoining part plays the role
* of sentinel, therefore this allows us to avoid
* the j >= left check on each iteration.
*/
for
(
int
j
,
i
=
left
+
1
;
i
<=
right
;
i
++)
{
float
ai
=
a
[
i
];
for
(
j
=
i
-
1
;
ai
<
a
[
j
];
j
--)
{
// assert j >= left;
a
[
j
+
1
]
=
a
[
j
];
}
a
[
j
+
1
]
=
ai
;
}
}
else
{
/*
/*
* For case of leftmost part traditional (without a sentinel)
* Traditional (without sentinel) insertion sort,
* insertion sort, optimized for server JVM, is used.
* optimized for server VM, is used in case of
* the leftmost part.
*/
*/
for
(
int
i
=
left
,
j
=
i
;
i
<
right
;
j
=
++
i
)
{
for
(
int
i
=
left
,
j
=
i
;
i
<
right
;
j
=
++
i
)
{
float
ai
=
a
[
i
+
1
];
float
ai
=
a
[
i
+
1
];
...
@@ -2020,12 +1701,54 @@ final class DualPivotQuicksort {
...
@@ -2020,12 +1701,54 @@ final class DualPivotQuicksort {
}
}
a
[
j
+
1
]
=
ai
;
a
[
j
+
1
]
=
ai
;
}
}
}
else
{
/*
* Skip the longest ascending sequence.
*/
do
{
if
(
left
++
>=
right
)
{
return
;
}
}
while
(
a
[
left
-
1
]
<=
a
[
left
]);
/*
* 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 best improved algorithm, so called pair insertion
* sort, which is faster than traditional implementation
* in the context of Dual-Pivot Quicksort.
*/
for
(
int
k
=
left
--;
(
left
+=
2
)
<=
right
;
)
{
float
a1
,
a2
;
k
=
left
-
1
;
if
(
a
[
k
]
<
a
[
left
])
{
a2
=
a
[
k
];
a1
=
a
[
left
];
}
else
{
a1
=
a
[
k
];
a2
=
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
;
}
float
last
=
a
[
right
];
while
(
last
<
a
[--
right
])
{
a
[
right
+
1
]
=
a
[
right
];
}
a
[
right
+
1
]
=
last
;
}
}
return
;
return
;
}
}
// Inexpensive approximation of length / 7
// Inexpensive approximation of length / 7
int
seventh
=
(
length
>>
>
3
)
+
(
length
>
>>
6
)
+
1
;
int
seventh
=
(
length
>>
3
)
+
(
length
>>
6
)
+
1
;
/*
/*
* Sort five evenly spaced elements around (and including) the
* Sort five evenly spaced elements around (and including) the
...
@@ -2107,10 +1830,14 @@ final class DualPivotQuicksort {
...
@@ -2107,10 +1830,14 @@ final class DualPivotQuicksort {
* Pointer k is the first index of ?-part.
* Pointer k is the first index of ?-part.
*/
*/
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++
)
{
for
(
int
k
=
less
-
1
;
++
k
<=
great
;
)
{
float
ak
=
a
[
k
];
float
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
/*
* Here and below we use "a[i] = b; i++;" instead
* of "a[i++] = b;" due to performance issue.
*/
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
less
++;
less
++;
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
...
@@ -2119,13 +1846,17 @@ final class DualPivotQuicksort {
...
@@ -2119,13 +1846,17 @@ final class DualPivotQuicksort {
break
outer
;
break
outer
;
}
}
}
}
if
(
a
[
great
]
<
pivot1
)
{
if
(
a
[
great
]
<
pivot1
)
{
// a[great] <= pivot2
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
a
[
great
];
a
[
less
]
=
a
[
great
];
less
++;
less
++;
}
else
{
// pivot1 <= a[great] <= pivot2
}
else
{
// pivot1 <= a[great] <= pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
}
}
/*
* Here and below we use "a[i] = b; i--;" instead
* of "a[i--] = b;" due to performance issue.
*/
a
[
great
]
=
ak
;
a
[
great
]
=
ak
;
great
--;
great
--;
}
}
...
@@ -2140,7 +1871,7 @@ final class DualPivotQuicksort {
...
@@ -2140,7 +1871,7 @@ final class DualPivotQuicksort {
sort
(
a
,
great
+
2
,
right
,
false
);
sort
(
a
,
great
+
2
,
right
,
false
);
/*
/*
* If center part is too large (comprises >
5
/7 of the array),
* If center part is too large (comprises >
4
/7 of the array),
* swap internal pivot values to ends.
* swap internal pivot values to ends.
*/
*/
if
(
less
<
e1
&&
e5
<
great
)
{
if
(
less
<
e1
&&
e5
<
great
)
{
...
@@ -2174,7 +1905,7 @@ final class DualPivotQuicksort {
...
@@ -2174,7 +1905,7 @@ final class DualPivotQuicksort {
* Pointer k is the first index of ?-part.
* Pointer k is the first index of ?-part.
*/
*/
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++
)
{
for
(
int
k
=
less
-
1
;
++
k
<=
great
;
)
{
float
ak
=
a
[
k
];
float
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
...
@@ -2186,7 +1917,7 @@ final class DualPivotQuicksort {
...
@@ -2186,7 +1917,7 @@ final class DualPivotQuicksort {
break
outer
;
break
outer
;
}
}
}
}
if
(
a
[
great
]
==
pivot1
)
{
if
(
a
[
great
]
==
pivot1
)
{
// a[great] < pivot2
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
/*
/*
* Even though a[great] equals to pivot1, the
* Even though a[great] equals to pivot1, the
...
@@ -2212,7 +1943,7 @@ final class DualPivotQuicksort {
...
@@ -2212,7 +1943,7 @@ final class DualPivotQuicksort {
}
else
{
// Pivots are equal
}
else
{
// Pivots are equal
/*
/*
* Partition degenerates to the traditional 3-way
* Partition
ing
degenerates to the traditional 3-way
* (or "Dutch National Flag") schema:
* (or "Dutch National Flag") schema:
*
*
* left part center part right part
* left part center part right part
...
@@ -2231,28 +1962,20 @@ final class DualPivotQuicksort {
...
@@ -2231,28 +1962,20 @@ final class DualPivotQuicksort {
*
*
* Pointer k is the first index of ?-part.
* Pointer k is the first index of ?-part.
*/
*/
for
(
int
k
=
le
ft
;
k
<=
great
;
k
++
)
{
for
(
int
k
=
le
ss
;
k
<=
great
;
++
k
)
{
if
(
a
[
k
]
==
pivot1
)
{
if
(
a
[
k
]
==
pivot1
)
{
continue
;
continue
;
}
}
float
ak
=
a
[
k
];
float
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
less
++;
less
++;
}
else
{
// a[k] > pivot1 - Move a[k] to right part
}
else
{
// a[k] > pivot1 - Move a[k] to right part
/*
* We know that pivot1 == a[e3] == pivot2. Thus, we know
* that great will still be >= k when the following loop
* terminates, even though we don't test for it explicitly.
* In other words, a[e3] acts as a sentinel for great.
*/
while
(
a
[
great
]
>
pivot1
)
{
while
(
a
[
great
]
>
pivot1
)
{
// assert great > k;
great
--;
great
--;
}
}
if
(
a
[
great
]
<
pivot1
)
{
if
(
a
[
great
]
<
pivot1
)
{
// a[great] <= pivot1
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
a
[
great
];
a
[
less
]
=
a
[
great
];
less
++;
less
++;
...
@@ -2272,73 +1995,40 @@ final class DualPivotQuicksort {
...
@@ -2272,73 +1995,40 @@ final class DualPivotQuicksort {
}
}
}
}
// Sort left and right parts recursively
/*
* Sort left and right parts recursively.
* All elements from center part are equal
* and, therefore, already sorted.
*/
sort
(
a
,
left
,
less
-
1
,
leftmost
);
sort
(
a
,
left
,
less
-
1
,
leftmost
);
sort
(
a
,
great
+
1
,
right
,
false
);
sort
(
a
,
great
+
1
,
right
,
false
);
}
}
}
}
/**
/**
* Sorts the specified array into ascending numerical order.
* Sorts the specified array.
*
* <p>The {@code <} relation does not provide a total order on all double
* values: {@code -0.0d == 0.0d} is {@code true} and a {@code Double.NaN}
* value compares neither less than, greater than, nor equal to any value,
* even itself. This method uses the total order imposed by the method
* {@link Double#compareTo}: {@code -0.0d} is treated as less than value
* {@code 0.0d} and {@code Double.NaN} is considered greater than any
* other value and all {@code Double.NaN} values are considered equal.
*
*
* @param a the array to be sorted
* @param a the array to be sorted
*/
*/
public
static
void
sort
(
double
[]
a
)
{
public
static
void
sort
(
double
[]
a
)
{
sortNegZeroAndNaN
(
a
,
0
,
a
.
length
-
1
);
sort
(
a
,
0
,
a
.
length
-
1
);
}
/**
* Sorts the specified range of the array into ascending order. The range
* to be sorted extends from the index {@code fromIndex}, inclusive, to
* the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the range to be sorted is empty (and the call is a no-op).
*
* <p>The {@code <} relation does not provide a total order on all double
* values: {@code -0.0d == 0.0d} is {@code true} and a {@code Double.NaN}
* value compares neither less than, greater than, nor equal to any value,
* even itself. This method uses the total order imposed by the method
* {@link Double#compareTo}: {@code -0.0d} is treated as less than value
* {@code 0.0d} and {@code Double.NaN} is considered greater than any
* other value and all {@code Double.NaN} values are considered equal.
*
* @param a the array to be sorted
* @param fromIndex the index of the first element, inclusive, to be sorted
* @param toIndex the index of the last element, exclusive, to be sorted
* @throws IllegalArgumentException if {@code fromIndex > toIndex}
* @throws ArrayIndexOutOfBoundsException
* if {@code fromIndex < 0} or {@code toIndex > a.length}
*/
public
static
void
sort
(
double
[]
a
,
int
fromIndex
,
int
toIndex
)
{
rangeCheck
(
a
.
length
,
fromIndex
,
toIndex
);
sortNegZeroAndNaN
(
a
,
fromIndex
,
toIndex
-
1
);
}
}
/**
/**
* Sorts the specified range of the array into ascending order. The
* Sorts the specified range of the array.
* sort is done in three phases to avoid expensive comparisons in the
* inner loop. The comparisons would be expensive due to anomalies
* associated with negative zero {@code -0.0d} and {@code Double.NaN}.
*
*
* @param a the array to be sorted
* @param a the array to be sorted
* @param left the index of the first element, inclusive, 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 right the index of the last element, inclusive, to be sorted
*/
*/
p
rivate
static
void
sortNegZeroAndNaN
(
double
[]
a
,
int
left
,
int
right
)
{
p
ublic
static
void
sort
(
double
[]
a
,
int
left
,
int
right
)
{
/*
/*
* Phase 1: Move NaNs to the end of the array.
* Phase 1: Move NaNs to the end of the array.
*/
*/
while
(
left
<=
right
&&
Double
.
isNaN
(
a
[
right
]))
{
while
(
left
<=
right
&&
Double
.
isNaN
(
a
[
right
]))
{
right
--;
right
--;
}
}
for
(
int
k
=
right
-
1
;
k
>=
left
;
k
--
)
{
for
(
int
k
=
right
;
--
k
>=
left
;
)
{
double
ak
=
a
[
k
];
double
ak
=
a
[
k
];
if
(
ak
!=
ak
)
{
// a[k] is NaN
if
(
ak
!=
ak
)
{
// a[k] is NaN
a
[
k
]
=
a
[
right
];
a
[
k
]
=
a
[
right
];
...
@@ -2358,7 +2048,7 @@ final class DualPivotQuicksort {
...
@@ -2358,7 +2048,7 @@ final class DualPivotQuicksort {
int
hi
=
right
;
int
hi
=
right
;
/*
/*
*
Search
first zero, or first positive, or last negative element.
*
Find the
first zero, or first positive, or last negative element.
*/
*/
while
(
left
<
hi
)
{
while
(
left
<
hi
)
{
int
middle
=
(
left
+
hi
)
>>>
1
;
int
middle
=
(
left
+
hi
)
>>>
1
;
...
@@ -2383,12 +2073,12 @@ final class DualPivotQuicksort {
...
@@ -2383,12 +2073,12 @@ final class DualPivotQuicksort {
*
*
* Partitioning:
* Partitioning:
*
*
* +---------------------------------------------------+
* +---------------------------------------------------
-
+
* | < 0.0 | -0.0 |
0.0 | ? ( >= 0.0 )
|
* | < 0.0 | -0.0 |
0.0 | ? ( >= 0.0 )
|
* +---------------------------------------------------+
* +---------------------------------------------------
-
+
* ^ ^
^
* ^ ^ ^
* | |
|
* | | |
* left p
k
* left p k
*
*
* Invariants:
* Invariants:
*
*
...
@@ -2399,53 +2089,36 @@ final class DualPivotQuicksort {
...
@@ -2399,53 +2089,36 @@ final class DualPivotQuicksort {
*
*
* Pointer k is the first index of ?-part.
* Pointer k is the first index of ?-part.
*/
*/
for
(
int
k
=
left
+
1
,
p
=
left
;
k
<=
right
;
k
++
)
{
for
(
int
k
=
left
,
p
=
left
-
1
;
++
k
<=
right
;
)
{
double
ak
=
a
[
k
];
double
ak
=
a
[
k
];
if
(
ak
!=
0.0d
)
{
if
(
ak
!=
0.0d
)
{
break
;
break
;
}
}
if
(
Double
.
doubleToRawLongBits
(
ak
)
<
0
)
{
// ak is -0.0d
if
(
Double
.
doubleToRawLongBits
(
ak
)
<
0
)
{
// ak is -0.0d
a
[
k
]
=
0.0d
;
a
[
k
]
=
0.0d
;
a
[
p
++
]
=
-
0.0d
;
a
[
++
p
]
=
-
0.0d
;
}
}
}
}
}
}
/**
/**
* Sorts the specified range of the array into ascending order by the
* Sorts the specified range of the array by Dual-Pivot Quicksort.
* Dual-Pivot Quicksort algorithm. This method differs from the public
* {@code sort} method in that the {@code right} index is inclusive,
* it does no range checking on {@code left} or {@code right}, and has
* boolean flag whether insertion sort with sentinel is used or not.
*
*
* @param a the array to be sorted
* @param a the array to be sorted
* @param left the index of the first element, inclusive, 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 right the index of the last element, inclusive, to be sorted
* @param leftmost indicates if th
e part is the most lef
t in the range
* @param leftmost indicates if th
is part is the leftmos
t in the range
*/
*/
private
static
void
sort
(
double
[]
a
,
int
left
,
int
right
,
boolean
leftmost
)
{
private
static
void
sort
(
double
[]
a
,
int
left
,
int
right
,
boolean
leftmost
)
{
int
length
=
right
-
left
+
1
;
int
length
=
right
-
left
+
1
;
// Use insertion sort on
tiny
arrays
// Use insertion sort on
small
arrays
if
(
length
<
INSERTION_SORT_THRESHOLD
)
{
if
(
length
<
INSERTION_SORT_THRESHOLD
)
{
if
(!
leftmost
)
{
if
(
leftmost
)
{
/*
* Every element in adjoining part plays the role
* of sentinel, therefore this allows us to avoid
* the j >= left check on each iteration.
*/
for
(
int
j
,
i
=
left
+
1
;
i
<=
right
;
i
++)
{
double
ai
=
a
[
i
];
for
(
j
=
i
-
1
;
ai
<
a
[
j
];
j
--)
{
// assert j >= left;
a
[
j
+
1
]
=
a
[
j
];
}
a
[
j
+
1
]
=
ai
;
}
}
else
{
/*
/*
* For case of leftmost part traditional (without a sentinel)
* Traditional (without sentinel) insertion sort,
* insertion sort, optimized for server JVM, is used.
* optimized for server VM, is used in case of
* the leftmost part.
*/
*/
for
(
int
i
=
left
,
j
=
i
;
i
<
right
;
j
=
++
i
)
{
for
(
int
i
=
left
,
j
=
i
;
i
<
right
;
j
=
++
i
)
{
double
ai
=
a
[
i
+
1
];
double
ai
=
a
[
i
+
1
];
...
@@ -2457,12 +2130,54 @@ final class DualPivotQuicksort {
...
@@ -2457,12 +2130,54 @@ final class DualPivotQuicksort {
}
}
a
[
j
+
1
]
=
ai
;
a
[
j
+
1
]
=
ai
;
}
}
}
else
{
/*
* Skip the longest ascending sequence.
*/
do
{
if
(
left
++
>=
right
)
{
return
;
}
}
while
(
a
[
left
-
1
]
<=
a
[
left
]);
/*
* 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 best improved algorithm, so called pair insertion
* sort, which is faster than traditional implementation
* in the context of Dual-Pivot Quicksort.
*/
for
(
int
k
=
left
--;
(
left
+=
2
)
<=
right
;
)
{
double
a1
,
a2
;
k
=
left
-
1
;
if
(
a
[
k
]
<
a
[
left
])
{
a2
=
a
[
k
];
a1
=
a
[
left
];
}
else
{
a1
=
a
[
k
];
a2
=
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
;
}
double
last
=
a
[
right
];
while
(
last
<
a
[--
right
])
{
a
[
right
+
1
]
=
a
[
right
];
}
a
[
right
+
1
]
=
last
;
}
}
return
;
return
;
}
}
// Inexpensive approximation of length / 7
// Inexpensive approximation of length / 7
int
seventh
=
(
length
>>
>
3
)
+
(
length
>
>>
6
)
+
1
;
int
seventh
=
(
length
>>
3
)
+
(
length
>>
6
)
+
1
;
/*
/*
* Sort five evenly spaced elements around (and including) the
* Sort five evenly spaced elements around (and including) the
...
@@ -2544,10 +2259,14 @@ final class DualPivotQuicksort {
...
@@ -2544,10 +2259,14 @@ final class DualPivotQuicksort {
* Pointer k is the first index of ?-part.
* Pointer k is the first index of ?-part.
*/
*/
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++
)
{
for
(
int
k
=
less
-
1
;
++
k
<=
great
;
)
{
double
ak
=
a
[
k
];
double
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
/*
* Here and below we use "a[i] = b; i++;" instead
* of "a[i++] = b;" due to performance issue.
*/
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
less
++;
less
++;
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
...
@@ -2556,13 +2275,17 @@ final class DualPivotQuicksort {
...
@@ -2556,13 +2275,17 @@ final class DualPivotQuicksort {
break
outer
;
break
outer
;
}
}
}
}
if
(
a
[
great
]
<
pivot1
)
{
if
(
a
[
great
]
<
pivot1
)
{
// a[great] <= pivot2
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
a
[
great
];
a
[
less
]
=
a
[
great
];
less
++;
less
++;
}
else
{
// pivot1 <= a[great] <= pivot2
}
else
{
// pivot1 <= a[great] <= pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
}
}
/*
* Here and below we use "a[i] = b; i--;" instead
* of "a[i--] = b;" due to performance issue.
*/
a
[
great
]
=
ak
;
a
[
great
]
=
ak
;
great
--;
great
--;
}
}
...
@@ -2577,7 +2300,7 @@ final class DualPivotQuicksort {
...
@@ -2577,7 +2300,7 @@ final class DualPivotQuicksort {
sort
(
a
,
great
+
2
,
right
,
false
);
sort
(
a
,
great
+
2
,
right
,
false
);
/*
/*
* If center part is too large (comprises >
5
/7 of the array),
* If center part is too large (comprises >
4
/7 of the array),
* swap internal pivot values to ends.
* swap internal pivot values to ends.
*/
*/
if
(
less
<
e1
&&
e5
<
great
)
{
if
(
less
<
e1
&&
e5
<
great
)
{
...
@@ -2611,7 +2334,7 @@ final class DualPivotQuicksort {
...
@@ -2611,7 +2334,7 @@ final class DualPivotQuicksort {
* Pointer k is the first index of ?-part.
* Pointer k is the first index of ?-part.
*/
*/
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++
)
{
for
(
int
k
=
less
-
1
;
++
k
<=
great
;
)
{
double
ak
=
a
[
k
];
double
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
...
@@ -2623,7 +2346,7 @@ final class DualPivotQuicksort {
...
@@ -2623,7 +2346,7 @@ final class DualPivotQuicksort {
break
outer
;
break
outer
;
}
}
}
}
if
(
a
[
great
]
==
pivot1
)
{
if
(
a
[
great
]
==
pivot1
)
{
// a[great] < pivot2
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
/*
/*
* Even though a[great] equals to pivot1, the
* Even though a[great] equals to pivot1, the
...
@@ -2649,7 +2372,7 @@ final class DualPivotQuicksort {
...
@@ -2649,7 +2372,7 @@ final class DualPivotQuicksort {
}
else
{
// Pivots are equal
}
else
{
// Pivots are equal
/*
/*
* Partition degenerates to the traditional 3-way
* Partition
ing
degenerates to the traditional 3-way
* (or "Dutch National Flag") schema:
* (or "Dutch National Flag") schema:
*
*
* left part center part right part
* left part center part right part
...
@@ -2668,28 +2391,20 @@ final class DualPivotQuicksort {
...
@@ -2668,28 +2391,20 @@ final class DualPivotQuicksort {
*
*
* Pointer k is the first index of ?-part.
* Pointer k is the first index of ?-part.
*/
*/
for
(
int
k
=
le
ft
;
k
<=
great
;
k
++
)
{
for
(
int
k
=
le
ss
;
k
<=
great
;
++
k
)
{
if
(
a
[
k
]
==
pivot1
)
{
if
(
a
[
k
]
==
pivot1
)
{
continue
;
continue
;
}
}
double
ak
=
a
[
k
];
double
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
less
++;
less
++;
}
else
{
// a[k] > pivot1 - Move a[k] to right part
}
else
{
// a[k] > pivot1 - Move a[k] to right part
/*
* We know that pivot1 == a[e3] == pivot2. Thus, we know
* that great will still be >= k when the following loop
* terminates, even though we don't test for it explicitly.
* In other words, a[e3] acts as a sentinel for great.
*/
while
(
a
[
great
]
>
pivot1
)
{
while
(
a
[
great
]
>
pivot1
)
{
// assert great > k;
great
--;
great
--;
}
}
if
(
a
[
great
]
<
pivot1
)
{
if
(
a
[
great
]
<
pivot1
)
{
// a[great] <= pivot1
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
a
[
great
];
a
[
less
]
=
a
[
great
];
less
++;
less
++;
...
@@ -2709,26 +2424,13 @@ final class DualPivotQuicksort {
...
@@ -2709,26 +2424,13 @@ final class DualPivotQuicksort {
}
}
}
}
// Sort left and right parts recursively
/*
* Sort left and right parts recursively.
* All elements from center part are equal
* and, therefore, already sorted.
*/
sort
(
a
,
left
,
less
-
1
,
leftmost
);
sort
(
a
,
left
,
less
-
1
,
leftmost
);
sort
(
a
,
great
+
1
,
right
,
false
);
sort
(
a
,
great
+
1
,
right
,
false
);
}
}
}
}
/**
* Checks that {@code fromIndex} and {@code toIndex} are in the range,
* otherwise throws an appropriate exception.
*/
private
static
void
rangeCheck
(
int
length
,
int
fromIndex
,
int
toIndex
)
{
if
(
fromIndex
>
toIndex
)
{
throw
new
IllegalArgumentException
(
"fromIndex: "
+
fromIndex
+
" > toIndex: "
+
toIndex
);
}
if
(
fromIndex
<
0
)
{
throw
new
ArrayIndexOutOfBoundsException
(
fromIndex
);
}
if
(
toIndex
>
length
)
{
throw
new
ArrayIndexOutOfBoundsException
(
toIndex
);
}
}
}
}
test/java/util/Arrays/Sorting.java
浏览文件 @
090a9645
...
@@ -23,7 +23,7 @@
...
@@ -23,7 +23,7 @@
/*
/*
* @test
* @test
* @bug 6880672 6896573 6899694
* @bug 6880672 6896573 6899694
6976036
* @summary Exercise Arrays.sort
* @summary Exercise Arrays.sort
* @build Sorting
* @build Sorting
* @run main Sorting -shortrun
* @run main Sorting -shortrun
...
@@ -50,10 +50,10 @@ public class Sorting {
...
@@ -50,10 +50,10 @@ public class Sorting {
1
,
2
,
3
,
21
,
55
,
1000
,
10000
};
1
,
2
,
3
,
21
,
55
,
1000
,
10000
};
// Random initial values used in a long run (default)
// Random initial values used in a long run (default)
private
static
final
long
[]
LONG_RUN_RANDOMS
=
{
666
,
0xC0FFEE
,
999
};
private
static
final
long
[]
LONG_RUN_RANDOMS
=
{
666
,
0xC0FFEE
,
999
};
// Random initial values used in a short run
// Random initial values used in a short run
private
static
final
long
[]
SHORT_RUN_RANDOMS
=
{
666
};
private
static
final
long
[]
SHORT_RUN_RANDOMS
=
{
666
};
public
static
void
main
(
String
[]
args
)
{
public
static
void
main
(
String
[]
args
)
{
boolean
shortRun
=
args
.
length
>
0
&&
args
[
0
].
equals
(
"-shortrun"
);
boolean
shortRun
=
args
.
length
>
0
&&
args
[
0
].
equals
(
"-shortrun"
);
...
@@ -81,6 +81,11 @@ public class Sorting {
...
@@ -81,6 +81,11 @@ public class Sorting {
for
(
long
random
:
randoms
)
{
for
(
long
random
:
randoms
)
{
reset
(
random
);
reset
(
random
);
for
(
int
length
:
lengths
)
{
testAndCheckWithInsertionSort
(
length
,
random
);
}
reset
(
random
);
for
(
int
length
:
lengths
)
{
for
(
int
length
:
lengths
)
{
testAndCheckWithCheckSum
(
length
,
random
);
testAndCheckWithCheckSum
(
length
,
random
);
}
}
...
@@ -268,9 +273,7 @@ public class Sorting {
...
@@ -268,9 +273,7 @@ public class Sorting {
" length = "
+
length
+
", m = "
+
m
);
" length = "
+
length
+
", m = "
+
m
);
Object
convertedGolden
=
converter
.
convert
(
golden
);
Object
convertedGolden
=
converter
.
convert
(
golden
);
Object
convertedTest
=
converter
.
convert
(
test
);
Object
convertedTest
=
converter
.
convert
(
test
);
// outArray(test);
sortSubArray
(
convertedTest
,
fromIndex
,
toIndex
);
sortSubArray
(
convertedTest
,
fromIndex
,
toIndex
);
// outArray(test);
checkSubArray
(
convertedTest
,
fromIndex
,
toIndex
,
m
);
checkSubArray
(
convertedTest
,
fromIndex
,
toIndex
,
m
);
}
}
}
}
...
@@ -311,7 +314,7 @@ public class Sorting {
...
@@ -311,7 +314,7 @@ public class Sorting {
private
static
void
checkSorted
(
Pair
[]
a
)
{
private
static
void
checkSorted
(
Pair
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
-
1
;
i
++)
{
for
(
int
i
=
0
;
i
<
a
.
length
-
1
;
i
++)
{
if
(
a
[
i
].
getKey
()
>
a
[
i
+
1
].
getKey
())
{
if
(
a
[
i
].
getKey
()
>
a
[
i
+
1
].
getKey
())
{
failed
(
i
,
""
+
a
[
i
].
getKey
(),
""
+
a
[
i
+
1
].
getKey
());
failed
Sort
(
i
,
""
+
a
[
i
].
getKey
(),
""
+
a
[
i
+
1
].
getKey
());
}
}
}
}
}
}
...
@@ -328,7 +331,7 @@ public class Sorting {
...
@@ -328,7 +331,7 @@ public class Sorting {
int
value4
=
a
[
i
++].
getValue
();
int
value4
=
a
[
i
++].
getValue
();
if
(!(
key1
==
key2
&&
key2
==
key3
&&
key3
==
key4
))
{
if
(!(
key1
==
key2
&&
key2
==
key3
&&
key3
==
key4
))
{
failed
(
"On position "
+
i
+
"
must
keys are different "
+
failed
(
"On position "
+
i
+
" keys are different "
+
key1
+
", "
+
key2
+
", "
+
key3
+
", "
+
key4
);
key1
+
", "
+
key2
+
", "
+
key3
+
", "
+
key4
);
}
}
if
(!(
value1
<
value2
&&
value2
<
value3
&&
value3
<
value4
))
{
if
(!(
value1
<
value2
&&
value2
<
value3
&&
value3
<
value4
))
{
...
@@ -385,6 +388,35 @@ public class Sorting {
...
@@ -385,6 +388,35 @@ public class Sorting {
private
int
myValue
;
private
int
myValue
;
}
}
private
static
void
testAndCheckWithInsertionSort
(
int
length
,
long
random
)
{
if
(
length
>
1000
)
{
return
;
}
ourDescription
=
"Check sorting with insertion sort"
;
int
[]
golden
=
new
int
[
length
];
for
(
int
m
=
1
;
m
<
2
*
length
;
m
*=
2
)
{
for
(
UnsortedBuilder
builder
:
UnsortedBuilder
.
values
())
{
builder
.
build
(
golden
,
m
);
int
[]
test
=
golden
.
clone
();
for
(
TypeConverter
converter
:
TypeConverter
.
values
())
{
out
.
println
(
"Test 'insertion sort': "
+
converter
+
" "
+
builder
+
"random = "
+
random
+
", length = "
+
length
+
", m = "
+
m
);
Object
convertedGolden
=
converter
.
convert
(
golden
);
Object
convertedTest1
=
converter
.
convert
(
test
);
Object
convertedTest2
=
converter
.
convert
(
test
);
sort
(
convertedTest1
);
sortByInsertionSort
(
convertedTest2
);
compare
(
convertedTest1
,
convertedTest2
);
}
}
}
out
.
println
();
}
private
static
void
testAndCheckWithCheckSum
(
int
length
,
long
random
)
{
private
static
void
testAndCheckWithCheckSum
(
int
length
,
long
random
)
{
ourDescription
=
"Check sorting with check sum"
;
ourDescription
=
"Check sorting with check sum"
;
int
[]
golden
=
new
int
[
length
];
int
[]
golden
=
new
int
[
length
];
...
@@ -460,9 +492,7 @@ public class Sorting {
...
@@ -460,9 +492,7 @@ public class Sorting {
builder
.
build
(
golden
,
a
,
g
,
z
,
n
,
p
);
builder
.
build
(
golden
,
a
,
g
,
z
,
n
,
p
);
float
[]
test
=
golden
.
clone
();
float
[]
test
=
golden
.
clone
();
scramble
(
test
);
scramble
(
test
);
// outArray(test);
sort
(
test
);
sort
(
test
);
// outArray(test);
compare
(
test
,
golden
,
a
,
n
,
g
);
compare
(
test
,
golden
,
a
,
n
,
g
);
}
}
newLine
=
true
;
newLine
=
true
;
...
@@ -500,9 +530,7 @@ public class Sorting {
...
@@ -500,9 +530,7 @@ public class Sorting {
builder
.
build
(
golden
,
a
,
g
,
z
,
n
,
p
);
builder
.
build
(
golden
,
a
,
g
,
z
,
n
,
p
);
double
[]
test
=
golden
.
clone
();
double
[]
test
=
golden
.
clone
();
scramble
(
test
);
scramble
(
test
);
// outArray(test);
sort
(
test
);
sort
(
test
);
// outArray(test);
compare
(
test
,
golden
,
a
,
n
,
g
);
compare
(
test
,
golden
,
a
,
n
,
g
);
}
}
newLine
=
true
;
newLine
=
true
;
...
@@ -721,12 +749,12 @@ public class Sorting {
...
@@ -721,12 +749,12 @@ public class Sorting {
for
(
int
i
=
numNeg
;
i
<
numNeg
+
numNegZero
;
i
++)
{
for
(
int
i
=
numNeg
;
i
<
numNeg
+
numNegZero
;
i
++)
{
if
(
NEGATIVE_ZERO
!=
Float
.
floatToIntBits
(
a
[
i
]))
{
if
(
NEGATIVE_ZERO
!=
Float
.
floatToIntBits
(
a
[
i
]))
{
failed
(
"On position "
+
i
+
" must be -0.0
f
instead of "
+
a
[
i
]);
failed
(
"On position "
+
i
+
" must be -0.0 instead of "
+
a
[
i
]);
}
}
}
}
for
(
int
i
=
0
;
i
<
a
.
length
-
numNaN
;
i
++)
{
for
(
int
i
=
0
;
i
<
a
.
length
-
numNaN
;
i
++)
{
if
(
a
[
i
]
!=
b
[
i
])
{
if
(
a
[
i
]
!=
b
[
i
])
{
failed
(
i
,
""
+
a
[
i
],
""
+
b
[
i
]);
failed
Compare
(
i
,
""
+
a
[
i
],
""
+
b
[
i
]);
}
}
}
}
}
}
...
@@ -747,12 +775,12 @@ public class Sorting {
...
@@ -747,12 +775,12 @@ public class Sorting {
for
(
int
i
=
numNeg
;
i
<
numNeg
+
numNegZero
;
i
++)
{
for
(
int
i
=
numNeg
;
i
<
numNeg
+
numNegZero
;
i
++)
{
if
(
NEGATIVE_ZERO
!=
Double
.
doubleToLongBits
(
a
[
i
]))
{
if
(
NEGATIVE_ZERO
!=
Double
.
doubleToLongBits
(
a
[
i
]))
{
failed
(
"On position "
+
i
+
" must be -0.0
d
instead of "
+
a
[
i
]);
failed
(
"On position "
+
i
+
" must be -0.0 instead of "
+
a
[
i
]);
}
}
}
}
for
(
int
i
=
0
;
i
<
a
.
length
-
numNaN
;
i
++)
{
for
(
int
i
=
0
;
i
<
a
.
length
-
numNaN
;
i
++)
{
if
(
a
[
i
]
!=
b
[
i
])
{
if
(
a
[
i
]
!=
b
[
i
])
{
failed
(
i
,
""
+
a
[
i
],
""
+
b
[
i
]);
failed
Compare
(
i
,
""
+
a
[
i
],
""
+
b
[
i
]);
}
}
}
}
}
}
...
@@ -841,8 +869,8 @@ public class Sorting {
...
@@ -841,8 +869,8 @@ public class Sorting {
int
incCount
=
1
;
int
incCount
=
1
;
int
decCount
=
a
.
length
;
int
decCount
=
a
.
length
;
int
i
=
0
;
int
i
=
0
;
int
period
=
m
;
int
period
=
m
--
;
m
--;
while
(
true
)
{
while
(
true
)
{
for
(
int
k
=
1
;
k
<=
period
;
k
++)
{
for
(
int
k
=
1
;
k
<=
period
;
k
++)
{
if
(
i
>=
a
.
length
)
{
if
(
i
>=
a
.
length
)
{
...
@@ -922,6 +950,25 @@ public class Sorting {
...
@@ -922,6 +950,25 @@ public class Sorting {
}
}
}
}
private
static
void
checkWithCheckSum
(
Object
test
,
Object
golden
)
{
checkSorted
(
test
);
checkCheckSum
(
test
,
golden
);
}
private
static
void
failed
(
String
message
)
{
err
.
format
(
"\n*** TEST FAILED - %s.\n\n%s.\n\n"
,
ourDescription
,
message
);
throw
new
RuntimeException
(
"Test failed - see log file for details"
);
}
private
static
void
failedSort
(
int
index
,
String
value1
,
String
value2
)
{
failed
(
"Array is not sorted at "
+
index
+
"-th position: "
+
value1
+
" and "
+
value2
);
}
private
static
void
failedCompare
(
int
index
,
String
value1
,
String
value2
)
{
failed
(
"On position "
+
index
+
" must be "
+
value2
+
" instead of "
+
value1
);
}
private
static
void
compare
(
Object
test
,
Object
golden
)
{
private
static
void
compare
(
Object
test
,
Object
golden
)
{
if
(
test
instanceof
int
[])
{
if
(
test
instanceof
int
[])
{
compare
((
int
[])
test
,
(
int
[])
golden
);
compare
((
int
[])
test
,
(
int
[])
golden
);
...
@@ -945,56 +992,10 @@ public class Sorting {
...
@@ -945,56 +992,10 @@ public class Sorting {
}
}
}
}
private
static
void
checkWithCheckSum
(
Object
test
,
Object
golden
)
{
checkSorted
(
test
);
checkCheckSum
(
test
,
golden
);
}
private
static
void
failed
(
String
message
)
{
err
.
format
(
"\n*** TEST FAILED - %s\n\n%s\n\n"
,
ourDescription
,
message
);
throw
new
RuntimeException
(
"Test failed - see log file for details"
);
}
private
static
void
failed
(
int
index
,
String
value1
,
String
value2
)
{
failed
(
"Array is not sorted at "
+
index
+
"-th position: "
+
value1
+
" and "
+
value2
);
}
private
static
void
checkSorted
(
Object
object
)
{
if
(
object
instanceof
int
[])
{
checkSorted
((
int
[])
object
);
}
else
if
(
object
instanceof
long
[])
{
checkSorted
((
long
[])
object
);
}
else
if
(
object
instanceof
short
[])
{
checkSorted
((
short
[])
object
);
}
else
if
(
object
instanceof
byte
[])
{
checkSorted
((
byte
[])
object
);
}
else
if
(
object
instanceof
char
[])
{
checkSorted
((
char
[])
object
);
}
else
if
(
object
instanceof
float
[])
{
checkSorted
((
float
[])
object
);
}
else
if
(
object
instanceof
double
[])
{
checkSorted
((
double
[])
object
);
}
else
if
(
object
instanceof
Integer
[])
{
checkSorted
((
Integer
[])
object
);
}
else
{
failed
(
"Unknow type of array: "
+
object
+
" of class "
+
object
.
getClass
().
getName
());
}
}
private
static
void
compare
(
Integer
[]
a
,
Integer
[]
b
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
if
(
a
[
i
].
intValue
()
!=
b
[
i
].
intValue
())
{
failed
(
i
,
""
+
a
[
i
],
""
+
b
[
i
]);
}
}
}
private
static
void
compare
(
int
[]
a
,
int
[]
b
)
{
private
static
void
compare
(
int
[]
a
,
int
[]
b
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
if
(
a
[
i
]
!=
b
[
i
])
{
if
(
a
[
i
]
!=
b
[
i
])
{
failed
(
i
,
""
+
a
[
i
],
""
+
b
[
i
]);
failed
Compare
(
i
,
""
+
a
[
i
],
""
+
b
[
i
]);
}
}
}
}
}
}
...
@@ -1002,7 +1003,7 @@ public class Sorting {
...
@@ -1002,7 +1003,7 @@ public class Sorting {
private
static
void
compare
(
long
[]
a
,
long
[]
b
)
{
private
static
void
compare
(
long
[]
a
,
long
[]
b
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
if
(
a
[
i
]
!=
b
[
i
])
{
if
(
a
[
i
]
!=
b
[
i
])
{
failed
(
i
,
""
+
a
[
i
],
""
+
b
[
i
]);
failed
Compare
(
i
,
""
+
a
[
i
],
""
+
b
[
i
]);
}
}
}
}
}
}
...
@@ -1010,7 +1011,7 @@ public class Sorting {
...
@@ -1010,7 +1011,7 @@ public class Sorting {
private
static
void
compare
(
short
[]
a
,
short
[]
b
)
{
private
static
void
compare
(
short
[]
a
,
short
[]
b
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
if
(
a
[
i
]
!=
b
[
i
])
{
if
(
a
[
i
]
!=
b
[
i
])
{
failed
(
i
,
""
+
a
[
i
],
""
+
b
[
i
]);
failed
Compare
(
i
,
""
+
a
[
i
],
""
+
b
[
i
]);
}
}
}
}
}
}
...
@@ -1018,7 +1019,7 @@ public class Sorting {
...
@@ -1018,7 +1019,7 @@ public class Sorting {
private
static
void
compare
(
byte
[]
a
,
byte
[]
b
)
{
private
static
void
compare
(
byte
[]
a
,
byte
[]
b
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
if
(
a
[
i
]
!=
b
[
i
])
{
if
(
a
[
i
]
!=
b
[
i
])
{
failed
(
i
,
""
+
a
[
i
],
""
+
b
[
i
]);
failed
Compare
(
i
,
""
+
a
[
i
],
""
+
b
[
i
]);
}
}
}
}
}
}
...
@@ -1026,7 +1027,7 @@ public class Sorting {
...
@@ -1026,7 +1027,7 @@ public class Sorting {
private
static
void
compare
(
char
[]
a
,
char
[]
b
)
{
private
static
void
compare
(
char
[]
a
,
char
[]
b
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
if
(
a
[
i
]
!=
b
[
i
])
{
if
(
a
[
i
]
!=
b
[
i
])
{
failed
(
i
,
""
+
a
[
i
],
""
+
b
[
i
]);
failed
Compare
(
i
,
""
+
a
[
i
],
""
+
b
[
i
]);
}
}
}
}
}
}
...
@@ -1034,7 +1035,7 @@ public class Sorting {
...
@@ -1034,7 +1035,7 @@ public class Sorting {
private
static
void
compare
(
float
[]
a
,
float
[]
b
)
{
private
static
void
compare
(
float
[]
a
,
float
[]
b
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
if
(
a
[
i
]
!=
b
[
i
])
{
if
(
a
[
i
]
!=
b
[
i
])
{
failed
(
i
,
""
+
a
[
i
],
""
+
b
[
i
]);
failed
Compare
(
i
,
""
+
a
[
i
],
""
+
b
[
i
]);
}
}
}
}
}
}
...
@@ -1042,23 +1043,46 @@ public class Sorting {
...
@@ -1042,23 +1043,46 @@ public class Sorting {
private
static
void
compare
(
double
[]
a
,
double
[]
b
)
{
private
static
void
compare
(
double
[]
a
,
double
[]
b
)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
if
(
a
[
i
]
!=
b
[
i
])
{
if
(
a
[
i
]
!=
b
[
i
])
{
failed
(
i
,
""
+
a
[
i
],
""
+
b
[
i
]);
failed
Compare
(
i
,
""
+
a
[
i
],
""
+
b
[
i
]);
}
}
}
}
}
}
private
static
void
c
heckSorted
(
Integer
[]
a
)
{
private
static
void
c
ompare
(
Integer
[]
a
,
Integer
[]
b
)
{
for
(
int
i
=
0
;
i
<
a
.
length
-
1
;
i
++)
{
for
(
int
i
=
0
;
i
<
a
.
length
;
i
++)
{
if
(
a
[
i
].
intValue
()
>
a
[
i
+
1
].
intValue
()
)
{
if
(
a
[
i
].
compareTo
(
b
[
i
])
!=
0
)
{
failed
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
failed
Compare
(
i
,
""
+
a
[
i
],
""
+
b
[
i
]);
}
}
}
}
}
}
private
static
void
checkSorted
(
Object
object
)
{
if
(
object
instanceof
int
[])
{
checkSorted
((
int
[])
object
);
}
else
if
(
object
instanceof
long
[])
{
checkSorted
((
long
[])
object
);
}
else
if
(
object
instanceof
short
[])
{
checkSorted
((
short
[])
object
);
}
else
if
(
object
instanceof
byte
[])
{
checkSorted
((
byte
[])
object
);
}
else
if
(
object
instanceof
char
[])
{
checkSorted
((
char
[])
object
);
}
else
if
(
object
instanceof
float
[])
{
checkSorted
((
float
[])
object
);
}
else
if
(
object
instanceof
double
[])
{
checkSorted
((
double
[])
object
);
}
else
if
(
object
instanceof
Integer
[])
{
checkSorted
((
Integer
[])
object
);
}
else
{
failed
(
"Unknow type of array: "
+
object
+
" of class "
+
object
.
getClass
().
getName
());
}
}
private
static
void
checkSorted
(
int
[]
a
)
{
private
static
void
checkSorted
(
int
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
-
1
;
i
++)
{
for
(
int
i
=
0
;
i
<
a
.
length
-
1
;
i
++)
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
failed
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
failed
Sort
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
}
}
}
}
}
}
...
@@ -1066,7 +1090,7 @@ public class Sorting {
...
@@ -1066,7 +1090,7 @@ public class Sorting {
private
static
void
checkSorted
(
long
[]
a
)
{
private
static
void
checkSorted
(
long
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
-
1
;
i
++)
{
for
(
int
i
=
0
;
i
<
a
.
length
-
1
;
i
++)
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
failed
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
failed
Sort
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
}
}
}
}
}
}
...
@@ -1074,7 +1098,7 @@ public class Sorting {
...
@@ -1074,7 +1098,7 @@ public class Sorting {
private
static
void
checkSorted
(
short
[]
a
)
{
private
static
void
checkSorted
(
short
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
-
1
;
i
++)
{
for
(
int
i
=
0
;
i
<
a
.
length
-
1
;
i
++)
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
failed
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
failed
Sort
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
}
}
}
}
}
}
...
@@ -1082,7 +1106,7 @@ public class Sorting {
...
@@ -1082,7 +1106,7 @@ public class Sorting {
private
static
void
checkSorted
(
byte
[]
a
)
{
private
static
void
checkSorted
(
byte
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
-
1
;
i
++)
{
for
(
int
i
=
0
;
i
<
a
.
length
-
1
;
i
++)
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
failed
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
failed
Sort
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
}
}
}
}
}
}
...
@@ -1090,7 +1114,7 @@ public class Sorting {
...
@@ -1090,7 +1114,7 @@ public class Sorting {
private
static
void
checkSorted
(
char
[]
a
)
{
private
static
void
checkSorted
(
char
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
-
1
;
i
++)
{
for
(
int
i
=
0
;
i
<
a
.
length
-
1
;
i
++)
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
failed
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
failed
Sort
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
}
}
}
}
}
}
...
@@ -1098,7 +1122,7 @@ public class Sorting {
...
@@ -1098,7 +1122,7 @@ public class Sorting {
private
static
void
checkSorted
(
float
[]
a
)
{
private
static
void
checkSorted
(
float
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
-
1
;
i
++)
{
for
(
int
i
=
0
;
i
<
a
.
length
-
1
;
i
++)
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
failed
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
failed
Sort
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
}
}
}
}
}
}
...
@@ -1106,34 +1130,45 @@ public class Sorting {
...
@@ -1106,34 +1130,45 @@ public class Sorting {
private
static
void
checkSorted
(
double
[]
a
)
{
private
static
void
checkSorted
(
double
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
-
1
;
i
++)
{
for
(
int
i
=
0
;
i
<
a
.
length
-
1
;
i
++)
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
failed
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
failedSort
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
}
}
}
private
static
void
checkSorted
(
Integer
[]
a
)
{
for
(
int
i
=
0
;
i
<
a
.
length
-
1
;
i
++)
{
if
(
a
[
i
].
intValue
()
>
a
[
i
+
1
].
intValue
())
{
failedSort
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
}
}
}
}
}
}
private
static
void
checkCheckSum
(
Object
test
,
Object
golden
)
{
private
static
void
checkCheckSum
(
Object
test
,
Object
golden
)
{
if
(
checkSum
(
test
)
!=
checkSum
(
golden
))
{
if
(
checkSumXor
(
test
)
!=
checkSumXor
(
golden
))
{
failed
(
"It seems that original and sorted arrays are not identical"
);
failed
(
"Original and sorted arrays are not identical [xor]"
);
}
if
(
checkSumPlus
(
test
)
!=
checkSumPlus
(
golden
))
{
failed
(
"Original and sorted arrays are not identical [plus]"
);
}
}
}
}
private
static
int
checkSum
(
Object
object
)
{
private
static
int
checkSum
Xor
(
Object
object
)
{
if
(
object
instanceof
int
[])
{
if
(
object
instanceof
int
[])
{
return
checkSum
((
int
[])
object
);
return
checkSum
Xor
((
int
[])
object
);
}
else
if
(
object
instanceof
long
[])
{
}
else
if
(
object
instanceof
long
[])
{
return
checkSum
((
long
[])
object
);
return
checkSum
Xor
((
long
[])
object
);
}
else
if
(
object
instanceof
short
[])
{
}
else
if
(
object
instanceof
short
[])
{
return
checkSum
((
short
[])
object
);
return
checkSum
Xor
((
short
[])
object
);
}
else
if
(
object
instanceof
byte
[])
{
}
else
if
(
object
instanceof
byte
[])
{
return
checkSum
((
byte
[])
object
);
return
checkSum
Xor
((
byte
[])
object
);
}
else
if
(
object
instanceof
char
[])
{
}
else
if
(
object
instanceof
char
[])
{
return
checkSum
((
char
[])
object
);
return
checkSum
Xor
((
char
[])
object
);
}
else
if
(
object
instanceof
float
[])
{
}
else
if
(
object
instanceof
float
[])
{
return
checkSum
((
float
[])
object
);
return
checkSum
Xor
((
float
[])
object
);
}
else
if
(
object
instanceof
double
[])
{
}
else
if
(
object
instanceof
double
[])
{
return
checkSum
((
double
[])
object
);
return
checkSum
Xor
((
double
[])
object
);
}
else
if
(
object
instanceof
Integer
[])
{
}
else
if
(
object
instanceof
Integer
[])
{
return
checkSum
((
Integer
[])
object
);
return
checkSum
Xor
((
Integer
[])
object
);
}
else
{
}
else
{
failed
(
"Unknow type of array: "
+
object
+
" of class "
+
failed
(
"Unknow type of array: "
+
object
+
" of class "
+
object
.
getClass
().
getName
());
object
.
getClass
().
getName
());
...
@@ -1141,76 +1176,275 @@ public class Sorting {
...
@@ -1141,76 +1176,275 @@ public class Sorting {
}
}
}
}
private
static
int
checkSum
(
Integer
[]
a
)
{
private
static
int
checkSum
Xor
(
Integer
[]
a
)
{
int
check
Xor
Sum
=
0
;
int
checkSum
=
0
;
for
(
Integer
e
:
a
)
{
for
(
Integer
e
:
a
)
{
check
Xor
Sum
^=
e
.
intValue
();
checkSum
^=
e
.
intValue
();
}
}
return
check
Xor
Sum
;
return
checkSum
;
}
}
private
static
int
checkSum
(
int
[]
a
)
{
private
static
int
checkSum
Xor
(
int
[]
a
)
{
int
check
Xor
Sum
=
0
;
int
checkSum
=
0
;
for
(
int
e
:
a
)
{
for
(
int
e
:
a
)
{
check
Xor
Sum
^=
e
;
checkSum
^=
e
;
}
}
return
check
Xor
Sum
;
return
checkSum
;
}
}
private
static
int
checkSum
(
long
[]
a
)
{
private
static
int
checkSum
Xor
(
long
[]
a
)
{
long
check
Xor
Sum
=
0
;
long
checkSum
=
0
;
for
(
long
e
:
a
)
{
for
(
long
e
:
a
)
{
check
Xor
Sum
^=
e
;
checkSum
^=
e
;
}
}
return
(
int
)
check
Xor
Sum
;
return
(
int
)
checkSum
;
}
}
private
static
int
checkSum
(
short
[]
a
)
{
private
static
int
checkSum
Xor
(
short
[]
a
)
{
short
check
Xor
Sum
=
0
;
short
checkSum
=
0
;
for
(
short
e
:
a
)
{
for
(
short
e
:
a
)
{
check
Xor
Sum
^=
e
;
checkSum
^=
e
;
}
}
return
(
int
)
check
Xor
Sum
;
return
(
int
)
checkSum
;
}
}
private
static
int
checkSum
(
byte
[]
a
)
{
private
static
int
checkSum
Xor
(
byte
[]
a
)
{
byte
check
Xor
Sum
=
0
;
byte
checkSum
=
0
;
for
(
byte
e
:
a
)
{
for
(
byte
e
:
a
)
{
check
Xor
Sum
^=
e
;
checkSum
^=
e
;
}
}
return
(
int
)
check
Xor
Sum
;
return
(
int
)
checkSum
;
}
}
private
static
int
checkSum
(
char
[]
a
)
{
private
static
int
checkSum
Xor
(
char
[]
a
)
{
char
check
Xor
Sum
=
0
;
char
checkSum
=
0
;
for
(
char
e
:
a
)
{
for
(
char
e
:
a
)
{
check
Xor
Sum
^=
e
;
checkSum
^=
e
;
}
}
return
(
int
)
check
Xor
Sum
;
return
(
int
)
checkSum
;
}
}
private
static
int
checkSum
(
float
[]
a
)
{
private
static
int
checkSum
Xor
(
float
[]
a
)
{
int
check
Xor
Sum
=
0
;
int
checkSum
=
0
;
for
(
float
e
:
a
)
{
for
(
float
e
:
a
)
{
check
Xor
Sum
^=
(
int
)
e
;
checkSum
^=
(
int
)
e
;
}
}
return
check
Xor
Sum
;
return
checkSum
;
}
}
private
static
int
checkSum
(
double
[]
a
)
{
private
static
int
checkSum
Xor
(
double
[]
a
)
{
int
check
Xor
Sum
=
0
;
int
checkSum
=
0
;
for
(
double
e
:
a
)
{
for
(
double
e
:
a
)
{
checkXorSum
^=
(
int
)
e
;
checkSum
^=
(
int
)
e
;
}
return
checkSum
;
}
private
static
int
checkSumPlus
(
Object
object
)
{
if
(
object
instanceof
int
[])
{
return
checkSumPlus
((
int
[])
object
);
}
else
if
(
object
instanceof
long
[])
{
return
checkSumPlus
((
long
[])
object
);
}
else
if
(
object
instanceof
short
[])
{
return
checkSumPlus
((
short
[])
object
);
}
else
if
(
object
instanceof
byte
[])
{
return
checkSumPlus
((
byte
[])
object
);
}
else
if
(
object
instanceof
char
[])
{
return
checkSumPlus
((
char
[])
object
);
}
else
if
(
object
instanceof
float
[])
{
return
checkSumPlus
((
float
[])
object
);
}
else
if
(
object
instanceof
double
[])
{
return
checkSumPlus
((
double
[])
object
);
}
else
if
(
object
instanceof
Integer
[])
{
return
checkSumPlus
((
Integer
[])
object
);
}
else
{
failed
(
"Unknow type of array: "
+
object
+
" of class "
+
object
.
getClass
().
getName
());
return
-
1
;
}
}
private
static
int
checkSumPlus
(
int
[]
a
)
{
int
checkSum
=
0
;
for
(
int
e
:
a
)
{
checkSum
+=
e
;
}
return
checkSum
;
}
private
static
int
checkSumPlus
(
long
[]
a
)
{
long
checkSum
=
0
;
for
(
long
e
:
a
)
{
checkSum
+=
e
;
}
return
(
int
)
checkSum
;
}
private
static
int
checkSumPlus
(
short
[]
a
)
{
short
checkSum
=
0
;
for
(
short
e
:
a
)
{
checkSum
+=
e
;
}
return
(
int
)
checkSum
;
}
private
static
int
checkSumPlus
(
byte
[]
a
)
{
byte
checkSum
=
0
;
for
(
byte
e
:
a
)
{
checkSum
+=
e
;
}
return
(
int
)
checkSum
;
}
private
static
int
checkSumPlus
(
char
[]
a
)
{
char
checkSum
=
0
;
for
(
char
e
:
a
)
{
checkSum
+=
e
;
}
return
(
int
)
checkSum
;
}
private
static
int
checkSumPlus
(
float
[]
a
)
{
int
checkSum
=
0
;
for
(
float
e
:
a
)
{
checkSum
+=
(
int
)
e
;
}
return
checkSum
;
}
private
static
int
checkSumPlus
(
double
[]
a
)
{
int
checkSum
=
0
;
for
(
double
e
:
a
)
{
checkSum
+=
(
int
)
e
;
}
return
checkSum
;
}
private
static
int
checkSumPlus
(
Integer
[]
a
)
{
int
checkSum
=
0
;
for
(
Integer
e
:
a
)
{
checkSum
+=
e
.
intValue
();
}
return
checkSum
;
}
private
static
void
sortByInsertionSort
(
Object
object
)
{
if
(
object
instanceof
int
[])
{
sortByInsertionSort
((
int
[])
object
);
}
else
if
(
object
instanceof
long
[])
{
sortByInsertionSort
((
long
[])
object
);
}
else
if
(
object
instanceof
short
[])
{
sortByInsertionSort
((
short
[])
object
);
}
else
if
(
object
instanceof
byte
[])
{
sortByInsertionSort
((
byte
[])
object
);
}
else
if
(
object
instanceof
char
[])
{
sortByInsertionSort
((
char
[])
object
);
}
else
if
(
object
instanceof
float
[])
{
sortByInsertionSort
((
float
[])
object
);
}
else
if
(
object
instanceof
double
[])
{
sortByInsertionSort
((
double
[])
object
);
}
else
if
(
object
instanceof
Integer
[])
{
sortByInsertionSort
((
Integer
[])
object
);
}
else
{
failed
(
"Unknow type of array: "
+
object
+
" of class "
+
object
.
getClass
().
getName
());
}
}
private
static
void
sortByInsertionSort
(
int
[]
a
)
{
for
(
int
j
,
i
=
1
;
i
<
a
.
length
;
i
++)
{
int
ai
=
a
[
i
];
for
(
j
=
i
-
1
;
j
>=
0
&&
ai
<
a
[
j
];
j
--)
{
a
[
j
+
1
]
=
a
[
j
];
}
a
[
j
+
1
]
=
ai
;
}
}
private
static
void
sortByInsertionSort
(
long
[]
a
)
{
for
(
int
j
,
i
=
1
;
i
<
a
.
length
;
i
++)
{
long
ai
=
a
[
i
];
for
(
j
=
i
-
1
;
j
>=
0
&&
ai
<
a
[
j
];
j
--)
{
a
[
j
+
1
]
=
a
[
j
];
}
a
[
j
+
1
]
=
ai
;
}
}
private
static
void
sortByInsertionSort
(
short
[]
a
)
{
for
(
int
j
,
i
=
1
;
i
<
a
.
length
;
i
++)
{
short
ai
=
a
[
i
];
for
(
j
=
i
-
1
;
j
>=
0
&&
ai
<
a
[
j
];
j
--)
{
a
[
j
+
1
]
=
a
[
j
];
}
a
[
j
+
1
]
=
ai
;
}
}
private
static
void
sortByInsertionSort
(
byte
[]
a
)
{
for
(
int
j
,
i
=
1
;
i
<
a
.
length
;
i
++)
{
byte
ai
=
a
[
i
];
for
(
j
=
i
-
1
;
j
>=
0
&&
ai
<
a
[
j
];
j
--)
{
a
[
j
+
1
]
=
a
[
j
];
}
a
[
j
+
1
]
=
ai
;
}
}
private
static
void
sortByInsertionSort
(
char
[]
a
)
{
for
(
int
j
,
i
=
1
;
i
<
a
.
length
;
i
++)
{
char
ai
=
a
[
i
];
for
(
j
=
i
-
1
;
j
>=
0
&&
ai
<
a
[
j
];
j
--)
{
a
[
j
+
1
]
=
a
[
j
];
}
a
[
j
+
1
]
=
ai
;
}
}
private
static
void
sortByInsertionSort
(
float
[]
a
)
{
for
(
int
j
,
i
=
1
;
i
<
a
.
length
;
i
++)
{
float
ai
=
a
[
i
];
for
(
j
=
i
-
1
;
j
>=
0
&&
ai
<
a
[
j
];
j
--)
{
a
[
j
+
1
]
=
a
[
j
];
}
a
[
j
+
1
]
=
ai
;
}
}
private
static
void
sortByInsertionSort
(
double
[]
a
)
{
for
(
int
j
,
i
=
1
;
i
<
a
.
length
;
i
++)
{
double
ai
=
a
[
i
];
for
(
j
=
i
-
1
;
j
>=
0
&&
ai
<
a
[
j
];
j
--)
{
a
[
j
+
1
]
=
a
[
j
];
}
a
[
j
+
1
]
=
ai
;
}
}
private
static
void
sortByInsertionSort
(
Integer
[]
a
)
{
for
(
int
j
,
i
=
1
;
i
<
a
.
length
;
i
++)
{
Integer
ai
=
a
[
i
];
for
(
j
=
i
-
1
;
j
>=
0
&&
ai
<
a
[
j
];
j
--)
{
a
[
j
+
1
]
=
a
[
j
];
}
a
[
j
+
1
]
=
ai
;
}
}
return
checkXorSum
;
}
}
private
static
void
sort
(
Object
object
)
{
private
static
void
sort
(
Object
object
)
{
...
@@ -1292,7 +1526,7 @@ public class Sorting {
...
@@ -1292,7 +1526,7 @@ public class Sorting {
for
(
int
i
=
fromIndex
;
i
<
toIndex
-
1
;
i
++)
{
for
(
int
i
=
fromIndex
;
i
<
toIndex
-
1
;
i
++)
{
if
(
a
[
i
].
intValue
()
>
a
[
i
+
1
].
intValue
())
{
if
(
a
[
i
].
intValue
()
>
a
[
i
+
1
].
intValue
())
{
failed
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
failed
Sort
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
}
}
}
}
...
@@ -1314,7 +1548,7 @@ public class Sorting {
...
@@ -1314,7 +1548,7 @@ public class Sorting {
for
(
int
i
=
fromIndex
;
i
<
toIndex
-
1
;
i
++)
{
for
(
int
i
=
fromIndex
;
i
<
toIndex
-
1
;
i
++)
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
failed
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
failed
Sort
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
}
}
}
}
...
@@ -1336,7 +1570,7 @@ public class Sorting {
...
@@ -1336,7 +1570,7 @@ public class Sorting {
for
(
int
i
=
fromIndex
;
i
<
toIndex
-
1
;
i
++)
{
for
(
int
i
=
fromIndex
;
i
<
toIndex
-
1
;
i
++)
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
failed
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
failed
Sort
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
}
}
}
}
...
@@ -1358,7 +1592,7 @@ public class Sorting {
...
@@ -1358,7 +1592,7 @@ public class Sorting {
for
(
int
i
=
fromIndex
;
i
<
toIndex
-
1
;
i
++)
{
for
(
int
i
=
fromIndex
;
i
<
toIndex
-
1
;
i
++)
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
failed
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
failed
Sort
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
}
}
}
}
...
@@ -1380,7 +1614,7 @@ public class Sorting {
...
@@ -1380,7 +1614,7 @@ public class Sorting {
for
(
int
i
=
fromIndex
;
i
<
toIndex
-
1
;
i
++)
{
for
(
int
i
=
fromIndex
;
i
<
toIndex
-
1
;
i
++)
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
failed
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
failed
Sort
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
}
}
}
}
...
@@ -1402,7 +1636,7 @@ public class Sorting {
...
@@ -1402,7 +1636,7 @@ public class Sorting {
for
(
int
i
=
fromIndex
;
i
<
toIndex
-
1
;
i
++)
{
for
(
int
i
=
fromIndex
;
i
<
toIndex
-
1
;
i
++)
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
failed
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
failed
Sort
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
}
}
}
}
...
@@ -1424,7 +1658,7 @@ public class Sorting {
...
@@ -1424,7 +1658,7 @@ public class Sorting {
for
(
int
i
=
fromIndex
;
i
<
toIndex
-
1
;
i
++)
{
for
(
int
i
=
fromIndex
;
i
<
toIndex
-
1
;
i
++)
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
failed
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
failed
Sort
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
}
}
}
}
...
@@ -1446,7 +1680,7 @@ public class Sorting {
...
@@ -1446,7 +1680,7 @@ public class Sorting {
for
(
int
i
=
fromIndex
;
i
<
toIndex
-
1
;
i
++)
{
for
(
int
i
=
fromIndex
;
i
<
toIndex
-
1
;
i
++)
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
if
(
a
[
i
]
>
a
[
i
+
1
])
{
failed
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
failed
Sort
(
i
,
""
+
a
[
i
],
""
+
a
[
i
+
1
]);
}
}
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录