Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
0ca86caf
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看板
提交
0ca86caf
编写于
12月 08, 2009
作者:
J
jjb
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
6905046: More Dual-pivot quicksort improvements
Summary: More improvements from the DPQ team Reviewed-by: alanb
上级
399c52fb
变更
1
显示空白变更内容
内联
并排
Showing
1 changed file
with
627 addition
and
403 deletion
+627
-403
src/share/classes/java/util/DualPivotQuicksort.java
src/share/classes/java/util/DualPivotQuicksort.java
+627
-403
未找到文件。
src/share/classes/java/util/DualPivotQuicksort.java
浏览文件 @
0ca86caf
...
@@ -36,12 +36,12 @@ package java.util;
...
@@ -36,12 +36,12 @@ package java.util;
* @author Jon Bentley
* @author Jon Bentley
* @author Josh Bloch
* @author Josh Bloch
*
*
* @version 2009.11.
16 m765.827.v12a
* @version 2009.11.
29 m765.827.12i
*/
*/
final
class
DualPivotQuicksort
{
final
class
DualPivotQuicksort
{
/**
/**
*
Suppresses default constructor
.
*
Prevents instantiation
.
*/
*/
private
DualPivotQuicksort
()
{}
private
DualPivotQuicksort
()
{}
...
@@ -84,7 +84,7 @@ final class DualPivotQuicksort {
...
@@ -84,7 +84,7 @@ final class DualPivotQuicksort {
* Sorts the specified range of the array into ascending order. The range
* Sorts the specified range of the array into ascending order. The range
* to be sorted extends from the index {@code fromIndex}, inclusive, to
* to be sorted extends from the index {@code fromIndex}, inclusive, to
* the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the range to be sorted is empty.
* 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 fromIndex the index of the first element, inclusive, to be sorted
...
@@ -101,8 +101,8 @@ final class DualPivotQuicksort {
...
@@ -101,8 +101,8 @@ final class DualPivotQuicksort {
/**
/**
* Sorts the specified range of the array into ascending order. This
* Sorts the specified range of the array into ascending order. This
* method differs from the public {@code sort} method in that the
* method differs from the public {@code sort} method in that the
* {@code right} index is inclusive, and it does no range checking
on
* {@code right} index is inclusive, and it does no range checking
* {@code left} or {@code right}.
*
on
{@code left} or {@code right}.
*
*
* @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
...
@@ -111,13 +111,13 @@ final class DualPivotQuicksort {
...
@@ -111,13 +111,13 @@ final class DualPivotQuicksort {
private
static
void
doSort
(
int
[]
a
,
int
left
,
int
right
)
{
private
static
void
doSort
(
int
[]
a
,
int
left
,
int
right
)
{
// Use insertion sort on tiny arrays
// Use insertion sort on tiny arrays
if
(
right
-
left
+
1
<
INSERTION_SORT_THRESHOLD
)
{
if
(
right
-
left
+
1
<
INSERTION_SORT_THRESHOLD
)
{
for
(
int
k
=
left
+
1
;
k
<=
right
;
k
++)
{
for
(
int
i
=
left
+
1
;
i
<=
right
;
i
++)
{
int
a
k
=
a
[
k
];
int
a
i
=
a
[
i
];
int
j
;
int
j
;
for
(
j
=
k
-
1
;
j
>=
left
&&
ak
<
a
[
j
];
j
--)
{
for
(
j
=
i
-
1
;
j
>=
left
&&
ai
<
a
[
j
];
j
--)
{
a
[
j
+
1
]
=
a
[
j
];
a
[
j
+
1
]
=
a
[
j
];
}
}
a
[
j
+
1
]
=
a
k
;
a
[
j
+
1
]
=
a
i
;
}
}
}
else
{
// Use Dual-Pivot Quicksort on large arrays
}
else
{
// Use Dual-Pivot Quicksort on large arrays
dualPivotQuicksort
(
a
,
left
,
right
);
dualPivotQuicksort
(
a
,
left
,
right
);
...
@@ -162,7 +162,7 @@ final class DualPivotQuicksort {
...
@@ -162,7 +162,7 @@ final class DualPivotQuicksort {
* second terciles of the array. Note that pivot1 <= pivot2.
* second terciles of the array. Note that pivot1 <= pivot2.
*
*
* The pivots are stored in local variables, and the first and
* The pivots are stored in local variables, and the first and
* the last of the
sorted elements
are moved to the locations
* the last of the
elements to be sorted
are moved to the locations
* formerly occupied by the pivots. When partitioning is complete,
* formerly occupied by the pivots. When partitioning is complete,
* the pivots are swapped back into their final positions, and
* the pivots are swapped back into their final positions, and
* excluded from subsequent sorting.
* excluded from subsequent sorting.
...
@@ -170,27 +170,26 @@ final class DualPivotQuicksort {
...
@@ -170,27 +170,26 @@ final class DualPivotQuicksort {
int
pivot1
=
ae2
;
a
[
e2
]
=
a
[
left
];
int
pivot1
=
ae2
;
a
[
e2
]
=
a
[
left
];
int
pivot2
=
ae4
;
a
[
e4
]
=
a
[
right
];
int
pivot2
=
ae4
;
a
[
e4
]
=
a
[
right
];
/*
* Partitioning
*
* left part center part right part
* ------------------------------------------------------------
* [ < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 ]
* ------------------------------------------------------------
* ^ ^ ^
* | | |
* less k great
*/
// Pointers
// Pointers
int
less
=
left
+
1
;
// The index of first element of center part
int
less
=
left
+
1
;
// The index of first element of center part
int
great
=
right
-
1
;
// The index before first element of right part
int
great
=
right
-
1
;
// The index before first element of right part
boolean
pivotsDiffer
=
pivot1
!=
pivot2
;
boolean
pivotsDiffer
=
(
pivot1
!=
pivot2
)
;
if
(
pivotsDiffer
)
{
if
(
pivotsDiffer
)
{
/*
/*
* Partitioning:
*
* left part center part right part
* +------------------------------------------------------------+
* | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
* +------------------------------------------------------------+
* ^ ^ ^
* | | |
* less k great
*
* Invariants:
* Invariants:
*
* all in (left, less) < pivot1
* all in (left, less) < pivot1
* pivot1 <= all in [less, k) <= pivot2
* pivot1 <= all in [less, k) <= pivot2
* all in (great, right) > pivot2
* all in (great, right) > pivot2
...
@@ -200,37 +199,37 @@ final class DualPivotQuicksort {
...
@@ -200,37 +199,37 @@ final class DualPivotQuicksort {
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
int
ak
=
a
[
k
];
int
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
>
less
)
{
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
}
}
less
++;
less
++;
}
else
if
(
ak
>
pivot2
)
{
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
while
(
a
[
great
]
>
pivot2
)
{
while
(
a
[
great
]
>
pivot2
)
{
if
(
k
==
great
--
)
{
if
(
great
--
==
k
)
{
break
outer
;
break
outer
;
}
}
}
}
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
else
{
// pivot1 <= a[great] <= pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
a
[
great
--]
=
ak
;
a
[
great
--]
=
ak
;
if
((
ak
=
a
[
k
])
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
ak
;
}
}
}
}
}
}
}
else
{
// Pivots are equal
}
else
{
// Pivots are equal
/*
/*
* Partition degenerates to the traditional 3-way
* Partition degenerates to the traditional 3-way
,
*
(or "Dutch National Flag")
partition:
*
or "Dutch National Flag",
partition:
*
*
* left part center part right part
* left part center part right part
* -------------------------------------------------
* +----------------------------------------------+
* [ < pivot | == pivot | ? | > pivot ]
* | < pivot | == pivot | ? | > pivot |
* -------------------------------------------------
* +----------------------------------------------+
*
* ^ ^ ^
* ^ ^ ^
* | | |
* | | |
* less k great
* less k great
...
@@ -243,30 +242,34 @@ final class DualPivotQuicksort {
...
@@ -243,30 +242,34 @@ final class DualPivotQuicksort {
*
*
* Pointer k is the first index of ?-part
* Pointer k is the first index of ?-part
*/
*/
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
int
ak
=
a
[
k
];
int
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
if
(
ak
==
pivot1
)
{
continue
;
continue
;
}
}
if
(
ak
<
pivot1
)
{
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
>
less
)
{
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
}
}
less
++;
less
++;
}
else
{
// a[k] > pivot
}
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
)
{
if
(
k
==
great
--)
{
great
--;
break
outer
;
}
}
}
a
[
k
]
=
a
[
great
];
if
(
a
[
great
]
<
pivot1
)
{
a
[
great
--]
=
ak
;
if
((
ak
=
a
[
k
])
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
ak
;
a
[
less
++]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
else
{
// a[great] == pivot1
a
[
k
]
=
pivot1
;
a
[
great
--]
=
ak
;
}
}
}
}
}
}
...
@@ -289,26 +292,55 @@ final class DualPivotQuicksort {
...
@@ -289,26 +292,55 @@ final class DualPivotQuicksort {
}
}
/*
/*
* If center part is too large (comprises >
5/6 of
* If center part is too large (comprises >
2/3 of the array),
*
the array),
swap internal pivot values to ends
* swap internal pivot values to ends
*/
*/
if
(
less
<
e1
&&
e5
<
great
)
{
if
(
less
<
e1
&&
great
>
e5
)
{
while
(
a
[
less
]
==
pivot1
)
{
while
(
a
[
less
]
==
pivot1
)
{
less
++;
less
++;
}
}
while
(
a
[
great
]
==
pivot2
)
{
while
(
a
[
great
]
==
pivot2
)
{
great
--;
great
--;
}
}
for
(
int
k
=
less
+
1
;
k
<=
great
;
)
{
/*
* Partitioning:
*
* left part center part right part
* +----------------------------------------------------------+
* | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 |
* +----------------------------------------------------------+
* ^ ^ ^
* | | |
* 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
=
less
;
k
<=
great
;
k
++)
{
int
ak
=
a
[
k
];
int
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
if
(
ak
==
pivot2
)
{
// Move a[k] to right part
a
[
k
++]
=
a
[
less
];
while
(
a
[
great
]
==
pivot2
)
{
if
(
great
--
==
k
)
{
break
outer
;
}
}
if
(
a
[
great
]
==
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
a
[
less
++]
=
pivot1
;
}
else
if
(
ak
==
pivot2
)
{
}
else
{
// pivot1 < a[great] < pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
}
a
[
great
--]
=
pivot2
;
a
[
great
--]
=
pivot2
;
}
else
{
}
else
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
k
++;
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
}
}
}
}
}
}
...
@@ -330,7 +362,7 @@ final class DualPivotQuicksort {
...
@@ -330,7 +362,7 @@ final class DualPivotQuicksort {
* Sorts the specified range of the array into ascending order. The range
* Sorts the specified range of the array into ascending order. The range
* to be sorted extends from the index {@code fromIndex}, inclusive, to
* to be sorted extends from the index {@code fromIndex}, inclusive, to
* the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the range to be sorted is empty.
* 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 fromIndex the index of the first element, inclusive, to be sorted
...
@@ -357,13 +389,13 @@ final class DualPivotQuicksort {
...
@@ -357,13 +389,13 @@ final class DualPivotQuicksort {
private
static
void
doSort
(
long
[]
a
,
int
left
,
int
right
)
{
private
static
void
doSort
(
long
[]
a
,
int
left
,
int
right
)
{
// Use insertion sort on tiny arrays
// Use insertion sort on tiny arrays
if
(
right
-
left
+
1
<
INSERTION_SORT_THRESHOLD
)
{
if
(
right
-
left
+
1
<
INSERTION_SORT_THRESHOLD
)
{
for
(
int
k
=
left
+
1
;
k
<=
right
;
k
++)
{
for
(
int
i
=
left
+
1
;
i
<=
right
;
i
++)
{
long
a
k
=
a
[
k
];
long
a
i
=
a
[
i
];
int
j
;
int
j
;
for
(
j
=
k
-
1
;
j
>=
left
&&
ak
<
a
[
j
];
j
--)
{
for
(
j
=
i
-
1
;
j
>=
left
&&
ai
<
a
[
j
];
j
--)
{
a
[
j
+
1
]
=
a
[
j
];
a
[
j
+
1
]
=
a
[
j
];
}
}
a
[
j
+
1
]
=
a
k
;
a
[
j
+
1
]
=
a
i
;
}
}
}
else
{
// Use Dual-Pivot Quicksort on large arrays
}
else
{
// Use Dual-Pivot Quicksort on large arrays
dualPivotQuicksort
(
a
,
left
,
right
);
dualPivotQuicksort
(
a
,
left
,
right
);
...
@@ -408,7 +440,7 @@ final class DualPivotQuicksort {
...
@@ -408,7 +440,7 @@ final class DualPivotQuicksort {
* second terciles of the array. Note that pivot1 <= pivot2.
* second terciles of the array. Note that pivot1 <= pivot2.
*
*
* The pivots are stored in local variables, and the first and
* The pivots are stored in local variables, and the first and
* the last of the
sorted elements
are moved to the locations
* the last of the
elements to be sorted
are moved to the locations
* formerly occupied by the pivots. When partitioning is complete,
* formerly occupied by the pivots. When partitioning is complete,
* the pivots are swapped back into their final positions, and
* the pivots are swapped back into their final positions, and
* excluded from subsequent sorting.
* excluded from subsequent sorting.
...
@@ -416,27 +448,26 @@ final class DualPivotQuicksort {
...
@@ -416,27 +448,26 @@ final class DualPivotQuicksort {
long
pivot1
=
ae2
;
a
[
e2
]
=
a
[
left
];
long
pivot1
=
ae2
;
a
[
e2
]
=
a
[
left
];
long
pivot2
=
ae4
;
a
[
e4
]
=
a
[
right
];
long
pivot2
=
ae4
;
a
[
e4
]
=
a
[
right
];
/*
* Partitioning
*
* left part center part right part
* ------------------------------------------------------------
* [ < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 ]
* ------------------------------------------------------------
* ^ ^ ^
* | | |
* less k great
*/
// Pointers
// Pointers
int
less
=
left
+
1
;
// The index of first element of center part
int
less
=
left
+
1
;
// The index of first element of center part
int
great
=
right
-
1
;
// The index before first element of right part
int
great
=
right
-
1
;
// The index before first element of right part
boolean
pivotsDiffer
=
pivot1
!=
pivot2
;
boolean
pivotsDiffer
=
(
pivot1
!=
pivot2
)
;
if
(
pivotsDiffer
)
{
if
(
pivotsDiffer
)
{
/*
/*
* Partitioning:
*
* left part center part right part
* +------------------------------------------------------------+
* | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
* +------------------------------------------------------------+
* ^ ^ ^
* | | |
* less k great
*
* Invariants:
* Invariants:
*
* all in (left, less) < pivot1
* all in (left, less) < pivot1
* pivot1 <= all in [less, k) <= pivot2
* pivot1 <= all in [less, k) <= pivot2
* all in (great, right) > pivot2
* all in (great, right) > pivot2
...
@@ -446,37 +477,37 @@ final class DualPivotQuicksort {
...
@@ -446,37 +477,37 @@ final class DualPivotQuicksort {
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
long
ak
=
a
[
k
];
long
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
>
less
)
{
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
}
}
less
++;
less
++;
}
else
if
(
ak
>
pivot2
)
{
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
while
(
a
[
great
]
>
pivot2
)
{
while
(
a
[
great
]
>
pivot2
)
{
if
(
k
==
great
--
)
{
if
(
great
--
==
k
)
{
break
outer
;
break
outer
;
}
}
}
}
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
else
{
// pivot1 <= a[great] <= pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
a
[
great
--]
=
ak
;
a
[
great
--]
=
ak
;
if
((
ak
=
a
[
k
])
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
ak
;
}
}
}
}
}
}
}
else
{
// Pivots are equal
}
else
{
// Pivots are equal
/*
/*
* Partition degenerates to the traditional 3-way
* Partition degenerates to the traditional 3-way
,
*
(or "Dutch National Flag")
partition:
*
or "Dutch National Flag",
partition:
*
*
* left part center part right part
* left part center part right part
* -------------------------------------------------
* +----------------------------------------------+
* [ < pivot | == pivot | ? | > pivot ]
* | < pivot | == pivot | ? | > pivot |
* -------------------------------------------------
* +----------------------------------------------+
*
* ^ ^ ^
* ^ ^ ^
* | | |
* | | |
* less k great
* less k great
...
@@ -489,30 +520,34 @@ final class DualPivotQuicksort {
...
@@ -489,30 +520,34 @@ final class DualPivotQuicksort {
*
*
* Pointer k is the first index of ?-part
* Pointer k is the first index of ?-part
*/
*/
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
long
ak
=
a
[
k
];
long
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
if
(
ak
==
pivot1
)
{
continue
;
continue
;
}
}
if
(
ak
<
pivot1
)
{
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
>
less
)
{
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
}
}
less
++;
less
++;
}
else
{
// a[k] > pivot
}
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
)
{
if
(
k
==
great
--)
{
great
--;
break
outer
;
}
}
}
a
[
k
]
=
a
[
great
];
if
(
a
[
great
]
<
pivot1
)
{
a
[
great
--]
=
ak
;
if
((
ak
=
a
[
k
])
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
ak
;
a
[
less
++]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
else
{
// a[great] == pivot1
a
[
k
]
=
pivot1
;
a
[
great
--]
=
ak
;
}
}
}
}
}
}
...
@@ -535,26 +570,55 @@ final class DualPivotQuicksort {
...
@@ -535,26 +570,55 @@ final class DualPivotQuicksort {
}
}
/*
/*
* If center part is too large (comprises >
5/6 of
* If center part is too large (comprises >
2/3 of the array),
*
the array),
swap internal pivot values to ends
* swap internal pivot values to ends
*/
*/
if
(
less
<
e1
&&
e5
<
great
)
{
if
(
less
<
e1
&&
great
>
e5
)
{
while
(
a
[
less
]
==
pivot1
)
{
while
(
a
[
less
]
==
pivot1
)
{
less
++;
less
++;
}
}
while
(
a
[
great
]
==
pivot2
)
{
while
(
a
[
great
]
==
pivot2
)
{
great
--;
great
--;
}
}
for
(
int
k
=
less
+
1
;
k
<=
great
;
)
{
/*
* Partitioning:
*
* left part center part right part
* +----------------------------------------------------------+
* | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 |
* +----------------------------------------------------------+
* ^ ^ ^
* | | |
* 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
=
less
;
k
<=
great
;
k
++)
{
long
ak
=
a
[
k
];
long
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
if
(
ak
==
pivot2
)
{
// Move a[k] to right part
a
[
k
++]
=
a
[
less
];
while
(
a
[
great
]
==
pivot2
)
{
if
(
great
--
==
k
)
{
break
outer
;
}
}
if
(
a
[
great
]
==
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
a
[
less
++]
=
pivot1
;
}
else
if
(
ak
==
pivot2
)
{
}
else
{
// pivot1 < a[great] < pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
}
a
[
great
--]
=
pivot2
;
a
[
great
--]
=
pivot2
;
}
else
{
}
else
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
k
++;
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
}
}
}
}
}
}
...
@@ -576,7 +640,7 @@ final class DualPivotQuicksort {
...
@@ -576,7 +640,7 @@ final class DualPivotQuicksort {
* Sorts the specified range of the array into ascending order. The range
* Sorts the specified range of the array into ascending order. The range
* to be sorted extends from the index {@code fromIndex}, inclusive, to
* to be sorted extends from the index {@code fromIndex}, inclusive, to
* the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the range to be sorted is empty.
* 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 fromIndex the index of the first element, inclusive, to be sorted
...
@@ -606,13 +670,13 @@ final class DualPivotQuicksort {
...
@@ -606,13 +670,13 @@ final class DualPivotQuicksort {
private
static
void
doSort
(
short
[]
a
,
int
left
,
int
right
)
{
private
static
void
doSort
(
short
[]
a
,
int
left
,
int
right
)
{
// Use insertion sort on tiny arrays
// Use insertion sort on tiny arrays
if
(
right
-
left
+
1
<
INSERTION_SORT_THRESHOLD
)
{
if
(
right
-
left
+
1
<
INSERTION_SORT_THRESHOLD
)
{
for
(
int
k
=
left
+
1
;
k
<=
right
;
k
++)
{
for
(
int
i
=
left
+
1
;
i
<=
right
;
i
++)
{
short
a
k
=
a
[
k
];
short
a
i
=
a
[
i
];
int
j
;
int
j
;
for
(
j
=
k
-
1
;
j
>=
left
&&
ak
<
a
[
j
];
j
--)
{
for
(
j
=
i
-
1
;
j
>=
left
&&
ai
<
a
[
j
];
j
--)
{
a
[
j
+
1
]
=
a
[
j
];
a
[
j
+
1
]
=
a
[
j
];
}
}
a
[
j
+
1
]
=
a
k
;
a
[
j
+
1
]
=
a
i
;
}
}
}
else
if
(
right
-
left
+
1
>
COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR
)
{
}
else
if
(
right
-
left
+
1
>
COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR
)
{
// Use counting sort on huge arrays
// Use counting sort on huge arrays
...
@@ -671,7 +735,7 @@ final class DualPivotQuicksort {
...
@@ -671,7 +735,7 @@ final class DualPivotQuicksort {
* second terciles of the array. Note that pivot1 <= pivot2.
* second terciles of the array. Note that pivot1 <= pivot2.
*
*
* The pivots are stored in local variables, and the first and
* The pivots are stored in local variables, and the first and
* the last of the
sorted elements
are moved to the locations
* the last of the
elements to be sorted
are moved to the locations
* formerly occupied by the pivots. When partitioning is complete,
* formerly occupied by the pivots. When partitioning is complete,
* the pivots are swapped back into their final positions, and
* the pivots are swapped back into their final positions, and
* excluded from subsequent sorting.
* excluded from subsequent sorting.
...
@@ -679,27 +743,26 @@ final class DualPivotQuicksort {
...
@@ -679,27 +743,26 @@ final class DualPivotQuicksort {
short
pivot1
=
ae2
;
a
[
e2
]
=
a
[
left
];
short
pivot1
=
ae2
;
a
[
e2
]
=
a
[
left
];
short
pivot2
=
ae4
;
a
[
e4
]
=
a
[
right
];
short
pivot2
=
ae4
;
a
[
e4
]
=
a
[
right
];
/*
* Partitioning
*
* left part center part right part
* ------------------------------------------------------------
* [ < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 ]
* ------------------------------------------------------------
* ^ ^ ^
* | | |
* less k great
*/
// Pointers
// Pointers
int
less
=
left
+
1
;
// The index of first element of center part
int
less
=
left
+
1
;
// The index of first element of center part
int
great
=
right
-
1
;
// The index before first element of right part
int
great
=
right
-
1
;
// The index before first element of right part
boolean
pivotsDiffer
=
pivot1
!=
pivot2
;
boolean
pivotsDiffer
=
(
pivot1
!=
pivot2
)
;
if
(
pivotsDiffer
)
{
if
(
pivotsDiffer
)
{
/*
/*
* Partitioning:
*
* left part center part right part
* +------------------------------------------------------------+
* | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
* +------------------------------------------------------------+
* ^ ^ ^
* | | |
* less k great
*
* Invariants:
* Invariants:
*
* all in (left, less) < pivot1
* all in (left, less) < pivot1
* pivot1 <= all in [less, k) <= pivot2
* pivot1 <= all in [less, k) <= pivot2
* all in (great, right) > pivot2
* all in (great, right) > pivot2
...
@@ -709,37 +772,37 @@ final class DualPivotQuicksort {
...
@@ -709,37 +772,37 @@ final class DualPivotQuicksort {
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
short
ak
=
a
[
k
];
short
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
>
less
)
{
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
}
}
less
++;
less
++;
}
else
if
(
ak
>
pivot2
)
{
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
while
(
a
[
great
]
>
pivot2
)
{
while
(
a
[
great
]
>
pivot2
)
{
if
(
k
==
great
--
)
{
if
(
great
--
==
k
)
{
break
outer
;
break
outer
;
}
}
}
}
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
else
{
// pivot1 <= a[great] <= pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
a
[
great
--]
=
ak
;
a
[
great
--]
=
ak
;
if
((
ak
=
a
[
k
])
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
ak
;
}
}
}
}
}
}
}
else
{
// Pivots are equal
}
else
{
// Pivots are equal
/*
/*
* Partition degenerates to the traditional 3-way
* Partition degenerates to the traditional 3-way
,
*
(or "Dutch National Flag")
partition:
*
or "Dutch National Flag",
partition:
*
*
* left part center part right part
* left part center part right part
* -------------------------------------------------
* +----------------------------------------------+
* [ < pivot | == pivot | ? | > pivot ]
* | < pivot | == pivot | ? | > pivot |
* -------------------------------------------------
* +----------------------------------------------+
*
* ^ ^ ^
* ^ ^ ^
* | | |
* | | |
* less k great
* less k great
...
@@ -752,30 +815,34 @@ final class DualPivotQuicksort {
...
@@ -752,30 +815,34 @@ final class DualPivotQuicksort {
*
*
* Pointer k is the first index of ?-part
* Pointer k is the first index of ?-part
*/
*/
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
short
ak
=
a
[
k
];
short
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
if
(
ak
==
pivot1
)
{
continue
;
continue
;
}
}
if
(
ak
<
pivot1
)
{
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
>
less
)
{
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
}
}
less
++;
less
++;
}
else
{
// a[k] > pivot
}
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
)
{
if
(
k
==
great
--)
{
great
--;
break
outer
;
}
}
}
a
[
k
]
=
a
[
great
];
if
(
a
[
great
]
<
pivot1
)
{
a
[
great
--]
=
ak
;
if
((
ak
=
a
[
k
])
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
ak
;
a
[
less
++]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
else
{
// a[great] == pivot1
a
[
k
]
=
pivot1
;
a
[
great
--]
=
ak
;
}
}
}
}
}
}
...
@@ -798,26 +865,55 @@ final class DualPivotQuicksort {
...
@@ -798,26 +865,55 @@ final class DualPivotQuicksort {
}
}
/*
/*
* If center part is too large (comprises >
5/6 of
* If center part is too large (comprises >
2/3 of the array),
*
the array),
swap internal pivot values to ends
* swap internal pivot values to ends
*/
*/
if
(
less
<
e1
&&
e5
<
great
)
{
if
(
less
<
e1
&&
great
>
e5
)
{
while
(
a
[
less
]
==
pivot1
)
{
while
(
a
[
less
]
==
pivot1
)
{
less
++;
less
++;
}
}
while
(
a
[
great
]
==
pivot2
)
{
while
(
a
[
great
]
==
pivot2
)
{
great
--;
great
--;
}
}
for
(
int
k
=
less
+
1
;
k
<=
great
;
)
{
/*
* Partitioning:
*
* left part center part right part
* +----------------------------------------------------------+
* | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 |
* +----------------------------------------------------------+
* ^ ^ ^
* | | |
* 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
=
less
;
k
<=
great
;
k
++)
{
short
ak
=
a
[
k
];
short
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
if
(
ak
==
pivot2
)
{
// Move a[k] to right part
a
[
k
++]
=
a
[
less
];
while
(
a
[
great
]
==
pivot2
)
{
if
(
great
--
==
k
)
{
break
outer
;
}
}
if
(
a
[
great
]
==
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
a
[
less
++]
=
pivot1
;
}
else
if
(
ak
==
pivot2
)
{
}
else
{
// pivot1 < a[great] < pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
}
a
[
great
--]
=
pivot2
;
a
[
great
--]
=
pivot2
;
}
else
{
}
else
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
k
++;
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
}
}
}
}
}
}
...
@@ -839,7 +935,7 @@ final class DualPivotQuicksort {
...
@@ -839,7 +935,7 @@ final class DualPivotQuicksort {
* Sorts the specified range of the array into ascending order. The range
* Sorts the specified range of the array into ascending order. The range
* to be sorted extends from the index {@code fromIndex}, inclusive, to
* to be sorted extends from the index {@code fromIndex}, inclusive, to
* the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the range to be sorted is empty.
* 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 fromIndex the index of the first element, inclusive, to be sorted
...
@@ -869,13 +965,13 @@ final class DualPivotQuicksort {
...
@@ -869,13 +965,13 @@ final class DualPivotQuicksort {
private
static
void
doSort
(
char
[]
a
,
int
left
,
int
right
)
{
private
static
void
doSort
(
char
[]
a
,
int
left
,
int
right
)
{
// Use insertion sort on tiny arrays
// Use insertion sort on tiny arrays
if
(
right
-
left
+
1
<
INSERTION_SORT_THRESHOLD
)
{
if
(
right
-
left
+
1
<
INSERTION_SORT_THRESHOLD
)
{
for
(
int
k
=
left
+
1
;
k
<=
right
;
k
++)
{
for
(
int
i
=
left
+
1
;
i
<=
right
;
i
++)
{
char
a
k
=
a
[
k
];
char
a
i
=
a
[
i
];
int
j
;
int
j
;
for
(
j
=
k
-
1
;
j
>=
left
&&
ak
<
a
[
j
];
j
--)
{
for
(
j
=
i
-
1
;
j
>=
left
&&
ai
<
a
[
j
];
j
--)
{
a
[
j
+
1
]
=
a
[
j
];
a
[
j
+
1
]
=
a
[
j
];
}
}
a
[
j
+
1
]
=
a
k
;
a
[
j
+
1
]
=
a
i
;
}
}
}
else
if
(
right
-
left
+
1
>
COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR
)
{
}
else
if
(
right
-
left
+
1
>
COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR
)
{
// Use counting sort on huge arrays
// Use counting sort on huge arrays
...
@@ -932,7 +1028,7 @@ final class DualPivotQuicksort {
...
@@ -932,7 +1028,7 @@ final class DualPivotQuicksort {
* second terciles of the array. Note that pivot1 <= pivot2.
* second terciles of the array. Note that pivot1 <= pivot2.
*
*
* The pivots are stored in local variables, and the first and
* The pivots are stored in local variables, and the first and
* the last of the
sorted elements
are moved to the locations
* the last of the
elements to be sorted
are moved to the locations
* formerly occupied by the pivots. When partitioning is complete,
* formerly occupied by the pivots. When partitioning is complete,
* the pivots are swapped back into their final positions, and
* the pivots are swapped back into their final positions, and
* excluded from subsequent sorting.
* excluded from subsequent sorting.
...
@@ -940,27 +1036,26 @@ final class DualPivotQuicksort {
...
@@ -940,27 +1036,26 @@ final class DualPivotQuicksort {
char
pivot1
=
ae2
;
a
[
e2
]
=
a
[
left
];
char
pivot1
=
ae2
;
a
[
e2
]
=
a
[
left
];
char
pivot2
=
ae4
;
a
[
e4
]
=
a
[
right
];
char
pivot2
=
ae4
;
a
[
e4
]
=
a
[
right
];
/*
* Partitioning
*
* left part center part right part
* ------------------------------------------------------------
* [ < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 ]
* ------------------------------------------------------------
* ^ ^ ^
* | | |
* less k great
*/
// Pointers
// Pointers
int
less
=
left
+
1
;
// The index of first element of center part
int
less
=
left
+
1
;
// The index of first element of center part
int
great
=
right
-
1
;
// The index before first element of right part
int
great
=
right
-
1
;
// The index before first element of right part
boolean
pivotsDiffer
=
pivot1
!=
pivot2
;
boolean
pivotsDiffer
=
(
pivot1
!=
pivot2
)
;
if
(
pivotsDiffer
)
{
if
(
pivotsDiffer
)
{
/*
/*
* Partitioning:
*
* left part center part right part
* +------------------------------------------------------------+
* | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
* +------------------------------------------------------------+
* ^ ^ ^
* | | |
* less k great
*
* Invariants:
* Invariants:
*
* all in (left, less) < pivot1
* all in (left, less) < pivot1
* pivot1 <= all in [less, k) <= pivot2
* pivot1 <= all in [less, k) <= pivot2
* all in (great, right) > pivot2
* all in (great, right) > pivot2
...
@@ -970,37 +1065,37 @@ final class DualPivotQuicksort {
...
@@ -970,37 +1065,37 @@ final class DualPivotQuicksort {
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
char
ak
=
a
[
k
];
char
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
>
less
)
{
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
}
}
less
++;
less
++;
}
else
if
(
ak
>
pivot2
)
{
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
while
(
a
[
great
]
>
pivot2
)
{
while
(
a
[
great
]
>
pivot2
)
{
if
(
k
==
great
--
)
{
if
(
great
--
==
k
)
{
break
outer
;
break
outer
;
}
}
}
}
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
else
{
// pivot1 <= a[great] <= pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
a
[
great
--]
=
ak
;
a
[
great
--]
=
ak
;
if
((
ak
=
a
[
k
])
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
ak
;
}
}
}
}
}
}
}
else
{
// Pivots are equal
}
else
{
// Pivots are equal
/*
/*
* Partition degenerates to the traditional 3-way
* Partition degenerates to the traditional 3-way
,
*
(or "Dutch National Flag")
partition:
*
or "Dutch National Flag",
partition:
*
*
* left part center part right part
* left part center part right part
* -------------------------------------------------
* +----------------------------------------------+
* [ < pivot | == pivot | ? | > pivot ]
* | < pivot | == pivot | ? | > pivot |
* -------------------------------------------------
* +----------------------------------------------+
*
* ^ ^ ^
* ^ ^ ^
* | | |
* | | |
* less k great
* less k great
...
@@ -1013,30 +1108,34 @@ final class DualPivotQuicksort {
...
@@ -1013,30 +1108,34 @@ final class DualPivotQuicksort {
*
*
* Pointer k is the first index of ?-part
* Pointer k is the first index of ?-part
*/
*/
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
char
ak
=
a
[
k
];
char
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
if
(
ak
==
pivot1
)
{
continue
;
continue
;
}
}
if
(
ak
<
pivot1
)
{
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
>
less
)
{
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
}
}
less
++;
less
++;
}
else
{
// a[k] > pivot
}
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
)
{
if
(
k
==
great
--)
{
great
--;
break
outer
;
}
}
}
a
[
k
]
=
a
[
great
];
if
(
a
[
great
]
<
pivot1
)
{
a
[
great
--]
=
ak
;
if
((
ak
=
a
[
k
])
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
ak
;
a
[
less
++]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
else
{
// a[great] == pivot1
a
[
k
]
=
pivot1
;
a
[
great
--]
=
ak
;
}
}
}
}
}
}
...
@@ -1059,26 +1158,55 @@ final class DualPivotQuicksort {
...
@@ -1059,26 +1158,55 @@ final class DualPivotQuicksort {
}
}
/*
/*
* If center part is too large (comprises >
5/6 of
* If center part is too large (comprises >
2/3 of the array),
*
the array),
swap internal pivot values to ends
* swap internal pivot values to ends
*/
*/
if
(
less
<
e1
&&
e5
<
great
)
{
if
(
less
<
e1
&&
great
>
e5
)
{
while
(
a
[
less
]
==
pivot1
)
{
while
(
a
[
less
]
==
pivot1
)
{
less
++;
less
++;
}
}
while
(
a
[
great
]
==
pivot2
)
{
while
(
a
[
great
]
==
pivot2
)
{
great
--;
great
--;
}
}
for
(
int
k
=
less
+
1
;
k
<=
great
;
)
{
/*
* Partitioning:
*
* left part center part right part
* +----------------------------------------------------------+
* | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 |
* +----------------------------------------------------------+
* ^ ^ ^
* | | |
* 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
=
less
;
k
<=
great
;
k
++)
{
char
ak
=
a
[
k
];
char
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
if
(
ak
==
pivot2
)
{
// Move a[k] to right part
a
[
k
++]
=
a
[
less
];
while
(
a
[
great
]
==
pivot2
)
{
if
(
great
--
==
k
)
{
break
outer
;
}
}
if
(
a
[
great
]
==
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
a
[
less
++]
=
pivot1
;
}
else
if
(
ak
==
pivot2
)
{
}
else
{
// pivot1 < a[great] < pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
}
a
[
great
--]
=
pivot2
;
a
[
great
--]
=
pivot2
;
}
else
{
}
else
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
k
++;
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
}
}
}
}
}
}
...
@@ -1100,7 +1228,7 @@ final class DualPivotQuicksort {
...
@@ -1100,7 +1228,7 @@ final class DualPivotQuicksort {
* Sorts the specified range of the array into ascending order. The range
* Sorts the specified range of the array into ascending order. The range
* to be sorted extends from the index {@code fromIndex}, inclusive, to
* to be sorted extends from the index {@code fromIndex}, inclusive, to
* the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the range to be sorted is empty.
* 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 fromIndex the index of the first element, inclusive, to be sorted
...
@@ -1130,13 +1258,13 @@ final class DualPivotQuicksort {
...
@@ -1130,13 +1258,13 @@ final class DualPivotQuicksort {
private
static
void
doSort
(
byte
[]
a
,
int
left
,
int
right
)
{
private
static
void
doSort
(
byte
[]
a
,
int
left
,
int
right
)
{
// Use insertion sort on tiny arrays
// Use insertion sort on tiny arrays
if
(
right
-
left
+
1
<
INSERTION_SORT_THRESHOLD
)
{
if
(
right
-
left
+
1
<
INSERTION_SORT_THRESHOLD
)
{
for
(
int
k
=
left
+
1
;
k
<=
right
;
k
++)
{
for
(
int
i
=
left
+
1
;
i
<=
right
;
i
++)
{
byte
a
k
=
a
[
k
];
byte
a
i
=
a
[
i
];
int
j
;
int
j
;
for
(
j
=
k
-
1
;
j
>=
left
&&
ak
<
a
[
j
];
j
--)
{
for
(
j
=
i
-
1
;
j
>=
left
&&
ai
<
a
[
j
];
j
--)
{
a
[
j
+
1
]
=
a
[
j
];
a
[
j
+
1
]
=
a
[
j
];
}
}
a
[
j
+
1
]
=
a
k
;
a
[
j
+
1
]
=
a
i
;
}
}
}
else
if
(
right
-
left
+
1
>
COUNTING_SORT_THRESHOLD_FOR_BYTE
)
{
}
else
if
(
right
-
left
+
1
>
COUNTING_SORT_THRESHOLD_FOR_BYTE
)
{
// Use counting sort on huge arrays
// Use counting sort on huge arrays
...
@@ -1195,7 +1323,7 @@ final class DualPivotQuicksort {
...
@@ -1195,7 +1323,7 @@ final class DualPivotQuicksort {
* second terciles of the array. Note that pivot1 <= pivot2.
* second terciles of the array. Note that pivot1 <= pivot2.
*
*
* The pivots are stored in local variables, and the first and
* The pivots are stored in local variables, and the first and
* the last of the
sorted elements
are moved to the locations
* the last of the
elements to be sorted
are moved to the locations
* formerly occupied by the pivots. When partitioning is complete,
* formerly occupied by the pivots. When partitioning is complete,
* the pivots are swapped back into their final positions, and
* the pivots are swapped back into their final positions, and
* excluded from subsequent sorting.
* excluded from subsequent sorting.
...
@@ -1203,27 +1331,26 @@ final class DualPivotQuicksort {
...
@@ -1203,27 +1331,26 @@ final class DualPivotQuicksort {
byte
pivot1
=
ae2
;
a
[
e2
]
=
a
[
left
];
byte
pivot1
=
ae2
;
a
[
e2
]
=
a
[
left
];
byte
pivot2
=
ae4
;
a
[
e4
]
=
a
[
right
];
byte
pivot2
=
ae4
;
a
[
e4
]
=
a
[
right
];
/*
* Partitioning
*
* left part center part right part
* ------------------------------------------------------------
* [ < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 ]
* ------------------------------------------------------------
* ^ ^ ^
* | | |
* less k great
*/
// Pointers
// Pointers
int
less
=
left
+
1
;
// The index of first element of center part
int
less
=
left
+
1
;
// The index of first element of center part
int
great
=
right
-
1
;
// The index before first element of right part
int
great
=
right
-
1
;
// The index before first element of right part
boolean
pivotsDiffer
=
pivot1
!=
pivot2
;
boolean
pivotsDiffer
=
(
pivot1
!=
pivot2
)
;
if
(
pivotsDiffer
)
{
if
(
pivotsDiffer
)
{
/*
/*
* Partitioning:
*
* left part center part right part
* +------------------------------------------------------------+
* | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
* +------------------------------------------------------------+
* ^ ^ ^
* | | |
* less k great
*
* Invariants:
* Invariants:
*
* all in (left, less) < pivot1
* all in (left, less) < pivot1
* pivot1 <= all in [less, k) <= pivot2
* pivot1 <= all in [less, k) <= pivot2
* all in (great, right) > pivot2
* all in (great, right) > pivot2
...
@@ -1233,37 +1360,37 @@ final class DualPivotQuicksort {
...
@@ -1233,37 +1360,37 @@ final class DualPivotQuicksort {
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
byte
ak
=
a
[
k
];
byte
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
>
less
)
{
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
}
}
less
++;
less
++;
}
else
if
(
ak
>
pivot2
)
{
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
while
(
a
[
great
]
>
pivot2
)
{
while
(
a
[
great
]
>
pivot2
)
{
if
(
k
==
great
--
)
{
if
(
great
--
==
k
)
{
break
outer
;
break
outer
;
}
}
}
}
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
else
{
// pivot1 <= a[great] <= pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
a
[
great
--]
=
ak
;
a
[
great
--]
=
ak
;
if
((
ak
=
a
[
k
])
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
ak
;
}
}
}
}
}
}
}
else
{
// Pivots are equal
}
else
{
// Pivots are equal
/*
/*
* Partition degenerates to the traditional 3-way
* Partition degenerates to the traditional 3-way
,
*
(or "Dutch National Flag")
partition:
*
or "Dutch National Flag",
partition:
*
*
* left part center part right part
* left part center part right part
* -------------------------------------------------
* +----------------------------------------------+
* [ < pivot | == pivot | ? | > pivot ]
* | < pivot | == pivot | ? | > pivot |
* -------------------------------------------------
* +----------------------------------------------+
*
* ^ ^ ^
* ^ ^ ^
* | | |
* | | |
* less k great
* less k great
...
@@ -1276,30 +1403,34 @@ final class DualPivotQuicksort {
...
@@ -1276,30 +1403,34 @@ final class DualPivotQuicksort {
*
*
* Pointer k is the first index of ?-part
* Pointer k is the first index of ?-part
*/
*/
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
byte
ak
=
a
[
k
];
byte
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
if
(
ak
==
pivot1
)
{
continue
;
continue
;
}
}
if
(
ak
<
pivot1
)
{
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
>
less
)
{
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
}
}
less
++;
less
++;
}
else
{
// a[k] > pivot
}
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
)
{
if
(
k
==
great
--)
{
great
--;
break
outer
;
}
}
}
a
[
k
]
=
a
[
great
];
if
(
a
[
great
]
<
pivot1
)
{
a
[
great
--]
=
ak
;
if
((
ak
=
a
[
k
])
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
ak
;
a
[
less
++]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
else
{
// a[great] == pivot1
a
[
k
]
=
pivot1
;
a
[
great
--]
=
ak
;
}
}
}
}
}
}
...
@@ -1322,26 +1453,55 @@ final class DualPivotQuicksort {
...
@@ -1322,26 +1453,55 @@ final class DualPivotQuicksort {
}
}
/*
/*
* If center part is too large (comprises >
5/6 of
* If center part is too large (comprises >
2/3 of the array),
*
the array),
swap internal pivot values to ends
* swap internal pivot values to ends
*/
*/
if
(
less
<
e1
&&
e5
<
great
)
{
if
(
less
<
e1
&&
great
>
e5
)
{
while
(
a
[
less
]
==
pivot1
)
{
while
(
a
[
less
]
==
pivot1
)
{
less
++;
less
++;
}
}
while
(
a
[
great
]
==
pivot2
)
{
while
(
a
[
great
]
==
pivot2
)
{
great
--;
great
--;
}
}
for
(
int
k
=
less
+
1
;
k
<=
great
;
)
{
/*
* Partitioning:
*
* left part center part right part
* +----------------------------------------------------------+
* | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 |
* +----------------------------------------------------------+
* ^ ^ ^
* | | |
* 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
=
less
;
k
<=
great
;
k
++)
{
byte
ak
=
a
[
k
];
byte
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
if
(
ak
==
pivot2
)
{
// Move a[k] to right part
a
[
k
++]
=
a
[
less
];
while
(
a
[
great
]
==
pivot2
)
{
if
(
great
--
==
k
)
{
break
outer
;
}
}
if
(
a
[
great
]
==
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
a
[
less
++]
=
pivot1
;
}
else
if
(
ak
==
pivot2
)
{
}
else
{
// pivot1 < a[great] < pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
}
a
[
great
--]
=
pivot2
;
a
[
great
--]
=
pivot2
;
}
else
{
}
else
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
k
++;
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
}
}
}
}
}
}
...
@@ -1371,7 +1531,7 @@ final class DualPivotQuicksort {
...
@@ -1371,7 +1531,7 @@ final class DualPivotQuicksort {
* Sorts the specified range of the array into ascending order. The range
* Sorts the specified range of the array into ascending order. The range
* to be sorted extends from the index {@code fromIndex}, inclusive, to
* to be sorted extends from the index {@code fromIndex}, inclusive, to
* the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the range to be sorted is empty.
* 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
* <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}
* values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
...
@@ -1485,13 +1645,13 @@ final class DualPivotQuicksort {
...
@@ -1485,13 +1645,13 @@ final class DualPivotQuicksort {
private
static
void
doSort
(
float
[]
a
,
int
left
,
int
right
)
{
private
static
void
doSort
(
float
[]
a
,
int
left
,
int
right
)
{
// Use insertion sort on tiny arrays
// Use insertion sort on tiny arrays
if
(
right
-
left
+
1
<
INSERTION_SORT_THRESHOLD
)
{
if
(
right
-
left
+
1
<
INSERTION_SORT_THRESHOLD
)
{
for
(
int
k
=
left
+
1
;
k
<=
right
;
k
++)
{
for
(
int
i
=
left
+
1
;
i
<=
right
;
i
++)
{
float
a
k
=
a
[
k
];
float
a
i
=
a
[
i
];
int
j
;
int
j
;
for
(
j
=
k
-
1
;
j
>=
left
&&
ak
<
a
[
j
];
j
--)
{
for
(
j
=
i
-
1
;
j
>=
left
&&
ai
<
a
[
j
];
j
--)
{
a
[
j
+
1
]
=
a
[
j
];
a
[
j
+
1
]
=
a
[
j
];
}
}
a
[
j
+
1
]
=
a
k
;
a
[
j
+
1
]
=
a
i
;
}
}
}
else
{
// Use Dual-Pivot Quicksort on large arrays
}
else
{
// Use Dual-Pivot Quicksort on large arrays
dualPivotQuicksort
(
a
,
left
,
right
);
dualPivotQuicksort
(
a
,
left
,
right
);
...
@@ -1536,7 +1696,7 @@ final class DualPivotQuicksort {
...
@@ -1536,7 +1696,7 @@ final class DualPivotQuicksort {
* second terciles of the array. Note that pivot1 <= pivot2.
* second terciles of the array. Note that pivot1 <= pivot2.
*
*
* The pivots are stored in local variables, and the first and
* The pivots are stored in local variables, and the first and
* the last of the
sorted elements
are moved to the locations
* the last of the
elements to be sorted
are moved to the locations
* formerly occupied by the pivots. When partitioning is complete,
* formerly occupied by the pivots. When partitioning is complete,
* the pivots are swapped back into their final positions, and
* the pivots are swapped back into their final positions, and
* excluded from subsequent sorting.
* excluded from subsequent sorting.
...
@@ -1544,27 +1704,26 @@ final class DualPivotQuicksort {
...
@@ -1544,27 +1704,26 @@ final class DualPivotQuicksort {
float
pivot1
=
ae2
;
a
[
e2
]
=
a
[
left
];
float
pivot1
=
ae2
;
a
[
e2
]
=
a
[
left
];
float
pivot2
=
ae4
;
a
[
e4
]
=
a
[
right
];
float
pivot2
=
ae4
;
a
[
e4
]
=
a
[
right
];
/*
* Partitioning
*
* left part center part right part
* ------------------------------------------------------------
* [ < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 ]
* ------------------------------------------------------------
* ^ ^ ^
* | | |
* less k great
*/
// Pointers
// Pointers
int
less
=
left
+
1
;
// The index of first element of center part
int
less
=
left
+
1
;
// The index of first element of center part
int
great
=
right
-
1
;
// The index before first element of right part
int
great
=
right
-
1
;
// The index before first element of right part
boolean
pivotsDiffer
=
pivot1
!=
pivot2
;
boolean
pivotsDiffer
=
(
pivot1
!=
pivot2
)
;
if
(
pivotsDiffer
)
{
if
(
pivotsDiffer
)
{
/*
/*
* Partitioning:
*
* left part center part right part
* +------------------------------------------------------------+
* | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
* +------------------------------------------------------------+
* ^ ^ ^
* | | |
* less k great
*
* Invariants:
* Invariants:
*
* all in (left, less) < pivot1
* all in (left, less) < pivot1
* pivot1 <= all in [less, k) <= pivot2
* pivot1 <= all in [less, k) <= pivot2
* all in (great, right) > pivot2
* all in (great, right) > pivot2
...
@@ -1574,37 +1733,37 @@ final class DualPivotQuicksort {
...
@@ -1574,37 +1733,37 @@ final class DualPivotQuicksort {
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
float
ak
=
a
[
k
];
float
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
>
less
)
{
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
}
}
less
++;
less
++;
}
else
if
(
ak
>
pivot2
)
{
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
while
(
a
[
great
]
>
pivot2
)
{
while
(
a
[
great
]
>
pivot2
)
{
if
(
k
==
great
--
)
{
if
(
great
--
==
k
)
{
break
outer
;
break
outer
;
}
}
}
}
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
else
{
// pivot1 <= a[great] <= pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
a
[
great
--]
=
ak
;
a
[
great
--]
=
ak
;
if
((
ak
=
a
[
k
])
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
ak
;
}
}
}
}
}
}
}
else
{
// Pivots are equal
}
else
{
// Pivots are equal
/*
/*
* Partition degenerates to the traditional 3-way
* Partition degenerates to the traditional 3-way
,
*
(or "Dutch National Flag")
partition:
*
or "Dutch National Flag",
partition:
*
*
* left part center part right part
* left part center part right part
* -------------------------------------------------
* +----------------------------------------------+
* [ < pivot | == pivot | ? | > pivot ]
* | < pivot | == pivot | ? | > pivot |
* -------------------------------------------------
* +----------------------------------------------+
*
* ^ ^ ^
* ^ ^ ^
* | | |
* | | |
* less k great
* less k great
...
@@ -1617,30 +1776,34 @@ final class DualPivotQuicksort {
...
@@ -1617,30 +1776,34 @@ final class DualPivotQuicksort {
*
*
* Pointer k is the first index of ?-part
* Pointer k is the first index of ?-part
*/
*/
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
float
ak
=
a
[
k
];
float
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
if
(
ak
==
pivot1
)
{
continue
;
continue
;
}
}
if
(
ak
<
pivot1
)
{
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
>
less
)
{
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
}
}
less
++;
less
++;
}
else
{
// a[k] > pivot
}
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
)
{
if
(
k
==
great
--)
{
great
--;
break
outer
;
}
}
}
a
[
k
]
=
a
[
great
];
if
(
a
[
great
]
<
pivot1
)
{
a
[
great
--]
=
ak
;
if
((
ak
=
a
[
k
])
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
ak
;
a
[
less
++]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
else
{
// a[great] == pivot1
a
[
k
]
=
pivot1
;
a
[
great
--]
=
ak
;
}
}
}
}
}
}
...
@@ -1663,26 +1826,55 @@ final class DualPivotQuicksort {
...
@@ -1663,26 +1826,55 @@ final class DualPivotQuicksort {
}
}
/*
/*
* If center part is too large (comprises >
5/6 of
* If center part is too large (comprises >
2/3 of the array),
*
the array),
swap internal pivot values to ends
* swap internal pivot values to ends
*/
*/
if
(
less
<
e1
&&
e5
<
great
)
{
if
(
less
<
e1
&&
great
>
e5
)
{
while
(
a
[
less
]
==
pivot1
)
{
while
(
a
[
less
]
==
pivot1
)
{
less
++;
less
++;
}
}
while
(
a
[
great
]
==
pivot2
)
{
while
(
a
[
great
]
==
pivot2
)
{
great
--;
great
--;
}
}
for
(
int
k
=
less
+
1
;
k
<=
great
;
)
{
/*
* Partitioning:
*
* left part center part right part
* +----------------------------------------------------------+
* | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 |
* +----------------------------------------------------------+
* ^ ^ ^
* | | |
* 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
=
less
;
k
<=
great
;
k
++)
{
float
ak
=
a
[
k
];
float
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
if
(
ak
==
pivot2
)
{
// Move a[k] to right part
a
[
k
++]
=
a
[
less
];
while
(
a
[
great
]
==
pivot2
)
{
if
(
great
--
==
k
)
{
break
outer
;
}
}
if
(
a
[
great
]
==
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
a
[
less
++]
=
pivot1
;
}
else
if
(
ak
==
pivot2
)
{
}
else
{
// pivot1 < a[great] < pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
}
a
[
great
--]
=
pivot2
;
a
[
great
--]
=
pivot2
;
}
else
{
}
else
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
k
++;
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
}
}
}
}
}
}
...
@@ -1712,7 +1904,7 @@ final class DualPivotQuicksort {
...
@@ -1712,7 +1904,7 @@ final class DualPivotQuicksort {
* Sorts the specified range of the array into ascending order. The range
* Sorts the specified range of the array into ascending order. The range
* to be sorted extends from the index {@code fromIndex}, inclusive, to
* to be sorted extends from the index {@code fromIndex}, inclusive, to
* the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
* the range to be sorted is empty.
* 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
* <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}
* values: {@code -0.0d == 0.0d} is {@code true} and a {@code Double.NaN}
...
@@ -1826,13 +2018,13 @@ final class DualPivotQuicksort {
...
@@ -1826,13 +2018,13 @@ final class DualPivotQuicksort {
private
static
void
doSort
(
double
[]
a
,
int
left
,
int
right
)
{
private
static
void
doSort
(
double
[]
a
,
int
left
,
int
right
)
{
// Use insertion sort on tiny arrays
// Use insertion sort on tiny arrays
if
(
right
-
left
+
1
<
INSERTION_SORT_THRESHOLD
)
{
if
(
right
-
left
+
1
<
INSERTION_SORT_THRESHOLD
)
{
for
(
int
k
=
left
+
1
;
k
<=
right
;
k
++)
{
for
(
int
i
=
left
+
1
;
i
<=
right
;
i
++)
{
double
a
k
=
a
[
k
];
double
a
i
=
a
[
i
];
int
j
;
int
j
;
for
(
j
=
k
-
1
;
j
>=
left
&&
ak
<
a
[
j
];
j
--)
{
for
(
j
=
i
-
1
;
j
>=
left
&&
ai
<
a
[
j
];
j
--)
{
a
[
j
+
1
]
=
a
[
j
];
a
[
j
+
1
]
=
a
[
j
];
}
}
a
[
j
+
1
]
=
a
k
;
a
[
j
+
1
]
=
a
i
;
}
}
}
else
{
// Use Dual-Pivot Quicksort on large arrays
}
else
{
// Use Dual-Pivot Quicksort on large arrays
dualPivotQuicksort
(
a
,
left
,
right
);
dualPivotQuicksort
(
a
,
left
,
right
);
...
@@ -1877,7 +2069,7 @@ final class DualPivotQuicksort {
...
@@ -1877,7 +2069,7 @@ final class DualPivotQuicksort {
* second terciles of the array. Note that pivot1 <= pivot2.
* second terciles of the array. Note that pivot1 <= pivot2.
*
*
* The pivots are stored in local variables, and the first and
* The pivots are stored in local variables, and the first and
* the last of the
sorted elements
are moved to the locations
* the last of the
elements to be sorted
are moved to the locations
* formerly occupied by the pivots. When partitioning is complete,
* formerly occupied by the pivots. When partitioning is complete,
* the pivots are swapped back into their final positions, and
* the pivots are swapped back into their final positions, and
* excluded from subsequent sorting.
* excluded from subsequent sorting.
...
@@ -1885,27 +2077,26 @@ final class DualPivotQuicksort {
...
@@ -1885,27 +2077,26 @@ final class DualPivotQuicksort {
double
pivot1
=
ae2
;
a
[
e2
]
=
a
[
left
];
double
pivot1
=
ae2
;
a
[
e2
]
=
a
[
left
];
double
pivot2
=
ae4
;
a
[
e4
]
=
a
[
right
];
double
pivot2
=
ae4
;
a
[
e4
]
=
a
[
right
];
/*
* Partitioning
*
* left part center part right part
* ------------------------------------------------------------
* [ < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 ]
* ------------------------------------------------------------
* ^ ^ ^
* | | |
* less k great
*/
// Pointers
// Pointers
int
less
=
left
+
1
;
// The index of first element of center part
int
less
=
left
+
1
;
// The index of first element of center part
int
great
=
right
-
1
;
// The index before first element of right part
int
great
=
right
-
1
;
// The index before first element of right part
boolean
pivotsDiffer
=
pivot1
!=
pivot2
;
boolean
pivotsDiffer
=
(
pivot1
!=
pivot2
)
;
if
(
pivotsDiffer
)
{
if
(
pivotsDiffer
)
{
/*
/*
* Partitioning:
*
* left part center part right part
* +------------------------------------------------------------+
* | < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 |
* +------------------------------------------------------------+
* ^ ^ ^
* | | |
* less k great
*
* Invariants:
* Invariants:
*
* all in (left, less) < pivot1
* all in (left, less) < pivot1
* pivot1 <= all in [less, k) <= pivot2
* pivot1 <= all in [less, k) <= pivot2
* all in (great, right) > pivot2
* all in (great, right) > pivot2
...
@@ -1915,37 +2106,37 @@ final class DualPivotQuicksort {
...
@@ -1915,37 +2106,37 @@ final class DualPivotQuicksort {
outer:
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
double
ak
=
a
[
k
];
double
ak
=
a
[
k
];
if
(
ak
<
pivot1
)
{
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
>
less
)
{
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
}
}
less
++;
less
++;
}
else
if
(
ak
>
pivot2
)
{
}
else
if
(
ak
>
pivot2
)
{
// Move a[k] to right part
while
(
a
[
great
]
>
pivot2
)
{
while
(
a
[
great
]
>
pivot2
)
{
if
(
k
==
great
--
)
{
if
(
great
--
==
k
)
{
break
outer
;
break
outer
;
}
}
}
}
if
(
a
[
great
]
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
else
{
// pivot1 <= a[great] <= pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
a
[
great
--]
=
ak
;
a
[
great
--]
=
ak
;
if
((
ak
=
a
[
k
])
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
ak
;
}
}
}
}
}
}
}
else
{
// Pivots are equal
}
else
{
// Pivots are equal
/*
/*
* Partition degenerates to the traditional 3-way
* Partition degenerates to the traditional 3-way
,
*
(or "Dutch National Flag")
partition:
*
or "Dutch National Flag",
partition:
*
*
* left part center part right part
* left part center part right part
* -------------------------------------------------
* +----------------------------------------------+
* [ < pivot | == pivot | ? | > pivot ]
* | < pivot | == pivot | ? | > pivot |
* -------------------------------------------------
* +----------------------------------------------+
*
* ^ ^ ^
* ^ ^ ^
* | | |
* | | |
* less k great
* less k great
...
@@ -1958,30 +2149,34 @@ final class DualPivotQuicksort {
...
@@ -1958,30 +2149,34 @@ final class DualPivotQuicksort {
*
*
* Pointer k is the first index of ?-part
* Pointer k is the first index of ?-part
*/
*/
outer:
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
for
(
int
k
=
less
;
k
<=
great
;
k
++)
{
double
ak
=
a
[
k
];
double
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
if
(
ak
==
pivot1
)
{
continue
;
continue
;
}
}
if
(
ak
<
pivot1
)
{
if
(
ak
<
pivot1
)
{
// Move a[k] to left part
if
(
k
>
less
)
{
if
(
k
!=
less
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
]
=
ak
;
a
[
less
]
=
ak
;
}
}
less
++;
less
++;
}
else
{
// a[k] > pivot
}
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
)
{
if
(
k
==
great
--)
{
great
--;
break
outer
;
}
}
}
a
[
k
]
=
a
[
great
];
if
(
a
[
great
]
<
pivot1
)
{
a
[
great
--]
=
ak
;
if
((
ak
=
a
[
k
])
<
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
ak
;
a
[
less
++]
=
a
[
great
];
a
[
great
--]
=
ak
;
}
else
{
// a[great] == pivot1
a
[
k
]
=
pivot1
;
a
[
great
--]
=
ak
;
}
}
}
}
}
}
...
@@ -2004,26 +2199,55 @@ final class DualPivotQuicksort {
...
@@ -2004,26 +2199,55 @@ final class DualPivotQuicksort {
}
}
/*
/*
* If center part is too large (comprises >
5/6 of
* If center part is too large (comprises >
2/3 of the array),
*
the array),
swap internal pivot values to ends
* swap internal pivot values to ends
*/
*/
if
(
less
<
e1
&&
e5
<
great
)
{
if
(
less
<
e1
&&
great
>
e5
)
{
while
(
a
[
less
]
==
pivot1
)
{
while
(
a
[
less
]
==
pivot1
)
{
less
++;
less
++;
}
}
while
(
a
[
great
]
==
pivot2
)
{
while
(
a
[
great
]
==
pivot2
)
{
great
--;
great
--;
}
}
for
(
int
k
=
less
+
1
;
k
<=
great
;
)
{
/*
* Partitioning:
*
* left part center part right part
* +----------------------------------------------------------+
* | == pivot1 | pivot1 < && < pivot2 | ? | == pivot2 |
* +----------------------------------------------------------+
* ^ ^ ^
* | | |
* 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
=
less
;
k
<=
great
;
k
++)
{
double
ak
=
a
[
k
];
double
ak
=
a
[
k
];
if
(
ak
==
pivot1
)
{
if
(
ak
==
pivot2
)
{
// Move a[k] to right part
a
[
k
++]
=
a
[
less
];
while
(
a
[
great
]
==
pivot2
)
{
if
(
great
--
==
k
)
{
break
outer
;
}
}
if
(
a
[
great
]
==
pivot1
)
{
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
a
[
less
++]
=
pivot1
;
}
else
if
(
ak
==
pivot2
)
{
}
else
{
// pivot1 < a[great] < pivot2
a
[
k
]
=
a
[
great
];
a
[
k
]
=
a
[
great
];
}
a
[
great
--]
=
pivot2
;
a
[
great
--]
=
pivot2
;
}
else
{
}
else
if
(
ak
==
pivot1
)
{
// Move a[k] to left part
k
++;
a
[
k
]
=
a
[
less
];
a
[
less
++]
=
pivot1
;
}
}
}
}
}
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录