Skip to content
项目
群组
代码片段
帮助
正在加载...
帮助
为 GitLab 提交贡献
登录/注册
切换导航
H
h2database
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
计划
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
Administrator
h2database
Commits
49d9d2ef
提交
49d9d2ef
authored
13 年前
作者:
Thomas Mueller
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
In-place stable sorting algorithms (just for fun).
上级
7bd0e66d
显示空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
794 行增加
和
0 行删除
+794
-0
TestAll.java
h2/src/test/org/h2/test/TestAll.java
+4
-0
TestSort.java
h2/src/test/org/h2/test/unit/TestSort.java
+158
-0
InPlaceStableMergeSort.java
h2/src/tools/org/h2/dev/sort/InPlaceStableMergeSort.java
+322
-0
InPlaceStableQuicksort.java
h2/src/tools/org/h2/dev/sort/InPlaceStableQuicksort.java
+310
-0
没有找到文件。
h2/src/test/org/h2/test/TestAll.java
浏览文件 @
49d9d2ef
...
@@ -139,6 +139,7 @@ import org.h2.test.unit.TestIntIntHashMap;
...
@@ -139,6 +139,7 @@ import org.h2.test.unit.TestIntIntHashMap;
import
org.h2.test.unit.TestJmx
;
import
org.h2.test.unit.TestJmx
;
import
org.h2.test.unit.TestModifyOnWrite
;
import
org.h2.test.unit.TestModifyOnWrite
;
import
org.h2.test.unit.TestObjectDeserialization
;
import
org.h2.test.unit.TestObjectDeserialization
;
import
org.h2.test.unit.TestSort
;
import
org.h2.test.unit.TestTraceSystem
;
import
org.h2.test.unit.TestTraceSystem
;
import
org.h2.test.unit.TestMathUtils
;
import
org.h2.test.unit.TestMathUtils
;
import
org.h2.test.unit.TestNetUtils
;
import
org.h2.test.unit.TestNetUtils
;
...
@@ -347,6 +348,8 @@ java org.h2.test.TestAll timer
...
@@ -347,6 +348,8 @@ java org.h2.test.TestAll timer
int
testWith_TCP_PROTOCOL_VERSION_10
;
int
testWith_TCP_PROTOCOL_VERSION_10
;
int
todoSupportTrailingSemicolonsInDatabaseUrl
;
// System.setProperty("h2.storeLocalTime", "true");
// System.setProperty("h2.storeLocalTime", "true");
// speedup
// speedup
...
@@ -691,6 +694,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
...
@@ -691,6 +694,7 @@ kill -9 `jps -l | grep "org.h2.test." | cut -d " " -f 1`
runTest
(
"org.h2.test.unit.TestServlet"
);
runTest
(
"org.h2.test.unit.TestServlet"
);
new
TestSecurity
().
runTest
(
this
);
new
TestSecurity
().
runTest
(
this
);
new
TestShell
().
runTest
(
this
);
new
TestShell
().
runTest
(
this
);
new
TestSort
().
runTest
(
this
);
new
TestStreams
().
runTest
(
this
);
new
TestStreams
().
runTest
(
this
);
new
TestStringCache
().
runTest
(
this
);
new
TestStringCache
().
runTest
(
this
);
new
TestStringUtils
().
runTest
(
this
);
new
TestStringUtils
().
runTest
(
this
);
...
...
This diff is collapsed.
Click to expand it.
h2/src/test/org/h2/test/unit/TestSort.java
0 → 100644
浏览文件 @
49d9d2ef
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
test
.
unit
;
import
java.util.Arrays
;
import
java.util.Comparator
;
import
java.util.Random
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
org.h2.dev.sort.InPlaceStableMergeSort
;
import
org.h2.dev.sort.InPlaceStableQuicksort
;
import
org.h2.test.TestBase
;
/**
* Tests the stable in-place sorting implementations.
*/
public
class
TestSort
extends
TestBase
{
AtomicInteger
compareCount
=
new
AtomicInteger
();
Comparator
<
Long
>
comp
=
new
Comparator
<
Long
>()
{
public
int
compare
(
Long
o1
,
Long
o2
)
{
compareCount
.
incrementAndGet
();
return
Long
.
valueOf
(
o1
>>
32
).
compareTo
(
o2
>>
32
);
}
};
private
Long
[]
array
=
new
Long
[
100000
];
private
Class
<?>
clazz
;
/**
* Run just this test.
*
* @param a ignored
*/
public
static
void
main
(
String
...
a
)
throws
Exception
{
TestBase
.
createCaller
().
init
().
test
();
}
public
void
test
()
throws
Exception
{
test
(
InPlaceStableMergeSort
.
class
);
test
(
InPlaceStableQuicksort
.
class
);
test
(
Arrays
.
class
);
}
void
test
(
Class
<?>
clazz
)
throws
Exception
{
this
.
clazz
=
clazz
;
ordered
(
array
);
shuffle
(
array
);
stabalize
(
array
);
test
(
"random"
);
ordered
(
array
);
stabalize
(
array
);
test
(
"ordered"
);
ordered
(
array
);
reverse
(
array
);
stabalize
(
array
);
test
(
"reverse"
);
ordered
(
array
);
stretch
(
array
);
shuffle
(
array
);
stabalize
(
array
);
test
(
"few random"
);
ordered
(
array
);
stretch
(
array
);
stabalize
(
array
);
test
(
"few ordered"
);
ordered
(
array
);
reverse
(
array
);
stretch
(
array
);
stabalize
(
array
);
test
(
"few reverse"
);
System
.
out
.
println
();
}
/**
* Sort the array and verify the result.
*
* @param type the type of data
*/
private
void
test
(
String
type
)
throws
Exception
{
compareCount
.
set
(
0
);
// long t = System.currentTimeMillis();
clazz
.
getMethod
(
"sort"
,
Object
[].
class
,
Comparator
.
class
).
invoke
(
null
,
array
,
comp
);
// System.out.printf(
// "%4d ms; %10d comparisons sorder: %s data: %s\n",
// (System.currentTimeMillis() - t),
// compareCount.get(), clazz, type);
verify
(
array
);
}
private
static
void
verify
(
Long
[]
array
)
{
long
last
=
Long
.
MIN_VALUE
;
int
len
=
array
.
length
;
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
long
x
=
array
[
i
];
long
x1
=
x
>>
32
,
x2
=
x
-
(
x1
<<
32
);
long
last1
=
last
>>
32
,
last2
=
last
-
(
last1
<<
32
);
if
(
x1
<
last1
)
{
if
(
array
.
length
<
1000
)
{
System
.
out
.
println
(
Arrays
.
toString
(
array
));
}
throw
new
RuntimeException
(
""
+
x
);
}
else
if
(
x1
==
last1
&&
x2
<
last2
)
{
if
(
array
.
length
<
1000
)
{
System
.
out
.
println
(
Arrays
.
toString
(
array
));
}
throw
new
RuntimeException
(
""
+
x
);
}
last
=
x
;
}
}
private
static
void
ordered
(
Long
[]
array
)
{
for
(
int
i
=
0
;
i
<
array
.
length
;
i
++)
{
array
[
i
]
=
(
long
)
i
;
}
}
private
static
void
stretch
(
Long
[]
array
)
{
for
(
int
i
=
array
.
length
-
1
;
i
>=
0
;
i
--)
{
array
[
i
]
=
array
[
i
/
4
];
}
}
private
static
void
reverse
(
Long
[]
array
)
{
for
(
int
i
=
0
;
i
<
array
.
length
/
2
;
i
++)
{
long
temp
=
array
[
i
];
array
[
i
]
=
array
[
array
.
length
-
i
-
1
];
array
[
array
.
length
-
i
-
1
]
=
temp
;
}
}
private
static
void
shuffle
(
Long
[]
array
)
{
Random
r
=
new
Random
(
1
);
for
(
int
i
=
0
;
i
<
array
.
length
;
i
++)
{
long
temp
=
array
[
i
];
int
j
=
r
.
nextInt
(
array
.
length
);
array
[
j
]
=
array
[
i
];
array
[
i
]
=
temp
;
}
}
private
static
void
stabalize
(
Long
[]
array
)
{
for
(
int
i
=
0
;
i
<
array
.
length
;
i
++)
{
array
[
i
]
=
(
array
[
i
]
<<
32
)
+
i
;
}
}
}
This diff is collapsed.
Click to expand it.
h2/src/tools/org/h2/dev/sort/InPlaceStableMergeSort.java
0 → 100644
浏览文件 @
49d9d2ef
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
dev
.
sort
;
import
java.util.Comparator
;
/**
* A stable merge sort implementation that uses at most O(log(n)) memory
* and O(n*log(n)*log(n)) time.
*
* @param <T> the element type
*/
public
class
InPlaceStableMergeSort
<
T
>
{
/**
* The minimum size of the temporary array. It is used to speed up sorting
* small blocks.
*/
private
static
final
int
TEMP_SIZE
=
1024
;
/**
* Blocks smaller than this number are sorted using binary insertion sort.
* This usually speeds up sorting.
*/
private
static
final
int
INSERTION_SORT_SIZE
=
16
;
/**
* The data array to sort.
*/
private
T
[]
data
;
/**
* The comparator.
*/
private
Comparator
<
T
>
comp
;
/**
* The temporary array.
*/
private
T
[]
temp
;
/**
* Sort an array using the given comparator.
*
* @param data the data array to sort
* @param comp the comparator
*/
public
static
<
T
>
void
sort
(
T
[]
data
,
Comparator
<
T
>
comp
)
{
new
InPlaceStableMergeSort
<
T
>().
sortArray
(
data
,
comp
);
}
/**
* Sort an array using the given comparator.
*
* @param data the data array to sort
* @param comp the comparator
*/
public
void
sortArray
(
T
[]
data
,
Comparator
<
T
>
comp
)
{
this
.
data
=
data
;
this
.
comp
=
comp
;
int
len
=
Math
.
max
((
int
)
(
100
*
Math
.
log
(
data
.
length
)),
TEMP_SIZE
);
len
=
Math
.
min
(
data
.
length
,
len
);
@SuppressWarnings
(
"unchecked"
)
T
[]
t
=
(
T
[])
new
Object
[
len
];
this
.
temp
=
t
;
mergeSort
(
0
,
data
.
length
-
1
);
}
/**
* Sort a block recursively using merge sort.
*
* @param from the index of the first entry to sort
* @param to the index of the last entry to sort
*/
void
mergeSort
(
int
from
,
int
to
)
{
if
(
to
-
from
<
INSERTION_SORT_SIZE
)
{
binaryInsertionSort
(
from
,
to
);
return
;
}
int
middle
=
(
from
+
to
)
>>>
1
;
mergeSort
(
from
,
middle
);
mergeSort
(
middle
+
1
,
to
);
merge
(
from
,
middle
+
1
,
to
);
}
/**
* Sort a block using the binary insertion sort algorithm.
*
* @param from the index of the first entry to sort
* @param to the index of the last entry to sort
*/
private
void
binaryInsertionSort
(
int
from
,
int
to
)
{
for
(
int
i
=
from
+
1
;
i
<=
to
;
i
++)
{
T
x
=
data
[
i
];
int
ins
=
binarySearch
(
x
,
from
,
i
-
1
);
for
(
int
j
=
i
-
1
;
j
>=
ins
;
j
--)
{
data
[
j
+
1
]
=
data
[
j
];
}
data
[
ins
]
=
x
;
}
}
/**
* Find the index of the element that is larger than x.
*
* @param x the element to search
* @param from the index of the first entry
* @param to the index of the last entry
* @return the position
*/
private
int
binarySearch
(
T
x
,
int
from
,
int
to
)
{
while
(
from
<=
to
)
{
int
m
=
(
from
+
to
)
>>>
1
;
if
(
comp
.
compare
(
x
,
data
[
m
])
>=
0
)
{
from
=
m
+
1
;
}
else
{
to
=
m
-
1
;
}
}
return
from
;
}
/**
* Merge two arrays.
*
* @param from the start of the first range
* @param second start of the second range
* @param to the last element of the second range
*/
private
void
merge
(
int
from
,
int
second
,
int
to
)
{
int
len1
=
second
-
from
,
len2
=
to
-
second
+
1
;
if
(
len1
==
0
||
len2
==
0
)
{
return
;
}
if
(
len1
+
len2
==
2
)
{
if
(
comp
.
compare
(
data
[
second
],
data
[
from
])
<
0
)
{
swap
(
data
,
second
,
from
);
}
return
;
}
if
(
len1
<=
temp
.
length
)
{
System
.
arraycopy
(
data
,
from
,
temp
,
0
,
len1
);
mergeSmall
(
data
,
from
,
temp
,
0
,
len1
-
1
,
data
,
second
,
to
);
return
;
}
else
if
(
len2
<=
temp
.
length
)
{
System
.
arraycopy
(
data
,
second
,
temp
,
0
,
len2
);
System
.
arraycopy
(
data
,
from
,
data
,
to
-
len1
+
1
,
len1
);
mergeSmall
(
data
,
from
,
data
,
to
-
len1
+
1
,
to
,
temp
,
0
,
len2
-
1
);
return
;
}
mergeBig
(
from
,
second
,
to
);
}
/**
* Merge two (large) arrays. This is done recursively by merging the
* beginning of both arrays, and then the end of both arrays.
*
* @param from the start of the first range
* @param second start of the second range
* @param to the last element of the second range
*/
private
void
mergeBig
(
int
from
,
int
second
,
int
to
)
{
int
len1
=
second
-
from
,
len2
=
to
-
second
+
1
;
int
firstCut
,
secondCut
,
newMid
;
if
(
len1
>
len2
)
{
firstCut
=
from
+
len1
/
2
;
secondCut
=
findLower
(
data
[
firstCut
],
second
,
to
);
int
len
=
secondCut
-
second
;
newMid
=
firstCut
+
len
;
}
else
{
int
len
=
len2
/
2
;
secondCut
=
second
+
len
;
firstCut
=
findUpper
(
data
[
secondCut
],
from
,
second
-
1
);
newMid
=
firstCut
+
len
;
}
swapBlocks
(
firstCut
,
second
,
secondCut
-
1
);
merge
(
from
,
firstCut
,
newMid
-
1
);
merge
(
newMid
,
secondCut
,
to
);
}
/**
* Merge two (small) arrays using the temporary array. This is done to speed
* up merging.
*
* @param target the target array
* @param pos the position of the first element in the target array
* @param s1 the first source array
* @param from1 the index of the first element in the first source array
* @param to1 the index of the last element in the first source array
* @param s2 the second source array
* @param from2 the index of the first element in the second source array
* @param to2 the index of the last element in the second source array
*/
private
void
mergeSmall
(
T
[]
target
,
int
pos
,
T
[]
s1
,
int
from1
,
int
to1
,
T
[]
s2
,
int
from2
,
int
to2
)
{
T
x1
=
s1
[
from1
],
x2
=
s2
[
from2
];
while
(
true
)
{
if
(
comp
.
compare
(
x1
,
x2
)
<=
0
)
{
target
[
pos
++]
=
x1
;
if
(++
from1
>
to1
)
{
System
.
arraycopy
(
s2
,
from2
,
target
,
pos
,
to2
-
from2
+
1
);
break
;
}
x1
=
s1
[
from1
];
}
else
{
target
[
pos
++]
=
x2
;
if
(++
from2
>
to2
)
{
System
.
arraycopy
(
s1
,
from1
,
target
,
pos
,
to1
-
from1
+
1
);
break
;
}
x2
=
s2
[
from2
];
}
}
}
/**
* Find the largest element in the sorted array that is smaller than x.
*
* @param x the element to search
* @param from the index of the first entry
* @param to the index of the last entry
* @return the index of the resulting element
*/
private
int
findLower
(
T
x
,
int
from
,
int
to
)
{
int
len
=
to
-
from
+
1
,
half
;
while
(
len
>
0
)
{
half
=
len
/
2
;
int
mid
=
from
+
half
;
if
(
comp
.
compare
(
data
[
mid
],
x
)
<
0
)
{
from
=
mid
+
1
;
len
=
len
-
half
-
1
;
}
else
{
len
=
half
;
}
}
return
from
;
}
/**
* Find the smallest element in the sorted array that is larger than or
* equal to x.
*
* @param x the element to search
* @param from the index of the first entry
* @param to the index of the last entry
* @return the index of the resulting element
*/
private
int
findUpper
(
T
x
,
int
from
,
int
to
)
{
int
len
=
to
-
from
+
1
,
half
;
while
(
len
>
0
)
{
half
=
len
/
2
;
int
mid
=
from
+
half
;
if
(
comp
.
compare
(
data
[
mid
],
x
)
<=
0
)
{
from
=
mid
+
1
;
len
=
len
-
half
-
1
;
}
else
{
len
=
half
;
}
}
return
from
;
}
/**
* Swap the elements of two blocks in the data array. Both blocks are next
* to each other (the second block starts just after the first block ends).
*
* @param from the index of the first element in the first block
* @param second the index of the first element in the second block
* @param to the index of the last element in the second block
*/
private
void
swapBlocks
(
int
from
,
int
second
,
int
to
)
{
int
len1
=
second
-
from
,
len2
=
to
-
second
+
1
;
if
(
len1
==
0
||
len2
==
0
)
{
return
;
}
if
(
len1
<
temp
.
length
)
{
System
.
arraycopy
(
data
,
from
,
temp
,
0
,
len1
);
System
.
arraycopy
(
data
,
second
,
data
,
from
,
len2
);
System
.
arraycopy
(
temp
,
0
,
data
,
from
+
len2
,
len1
);
return
;
}
else
if
(
len2
<
temp
.
length
)
{
System
.
arraycopy
(
data
,
second
,
temp
,
0
,
len2
);
System
.
arraycopy
(
data
,
from
,
data
,
from
+
len2
,
len1
);
System
.
arraycopy
(
temp
,
0
,
data
,
from
,
len2
);
return
;
}
reverseBlock
(
from
,
second
-
1
);
reverseBlock
(
second
,
to
);
reverseBlock
(
from
,
to
);
}
/**
* Reverse all elements in a block.
*
* @param from the index of the first element
* @param to the index of the last element
*/
private
void
reverseBlock
(
int
from
,
int
to
)
{
while
(
from
<
to
)
{
T
old
=
data
[
from
];
data
[
from
++]
=
data
[
to
];
data
[
to
--]
=
old
;
}
}
/**
* Swap two elements in the array.
*
* @param data the array
* @param a the index of the first element
* @param b the index of the second element
*/
private
void
swap
(
T
[]
data
,
int
a
,
int
b
)
{
T
temp
=
data
[
a
];
data
[
a
]
=
data
[
b
];
data
[
b
]
=
temp
;
}
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
h2/src/tools/org/h2/dev/sort/InPlaceStableQuicksort.java
0 → 100644
浏览文件 @
49d9d2ef
/*
* Copyright 2004-2011 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package
org
.
h2
.
dev
.
sort
;
import
java.util.Comparator
;
/**
* A stable quicksort implementation that uses O(log(n)) memory. It normally
* runs in O(n*log(n)*log(n)), but at most in O(n^2).
*
* @param <T> the element type
*/
public
class
InPlaceStableQuicksort
<
T
>
{
/**
* The minimum size of the temporary array. It is used to speed up sorting
* small blocks.
*/
private
static
final
int
TEMP_SIZE
=
1024
;
/**
* Blocks smaller than this number are sorted using binary insertion sort.
* This usually speeds up sorting.
*/
private
static
final
int
INSERTION_SORT_SIZE
=
16
;
/**
* The data array to sort.
*/
private
T
[]
data
;
/**
* The comparator.
*/
private
Comparator
<
T
>
comp
;
/**
* The temporary array.
*/
private
T
[]
temp
;
/**
* Sort an array using the given comparator.
*
* @param data the data array to sort
* @param comp the comparator
*/
public
static
<
T
>
void
sort
(
T
[]
data
,
Comparator
<
T
>
comp
)
{
new
InPlaceStableQuicksort
<
T
>().
sortArray
(
data
,
comp
);
}
/**
* Sort an array using the given comparator.
*
* @param data the data array to sort
* @param comp the comparator
*/
public
void
sortArray
(
T
[]
data
,
Comparator
<
T
>
comp
)
{
this
.
data
=
data
;
this
.
comp
=
comp
;
int
len
=
Math
.
max
((
int
)
(
100
*
Math
.
log
(
data
.
length
)),
TEMP_SIZE
);
len
=
Math
.
min
(
data
.
length
,
len
);
@SuppressWarnings
(
"unchecked"
)
T
[]
t
=
(
T
[])
new
Object
[
len
];
this
.
temp
=
t
;
quicksort
(
0
,
data
.
length
-
1
);
}
/**
* Sort a block using the quicksort algorithm.
*
* @param from the index of the first entry to sort
* @param to the index of the last entry to sort
*/
private
void
quicksort
(
int
from
,
int
to
)
{
while
(
to
>
from
)
{
if
(
to
-
from
<
INSERTION_SORT_SIZE
)
{
binaryInsertionSort
(
from
,
to
);
return
;
}
T
pivot
=
selectPivot
(
from
,
to
);
int
second
=
partition
(
pivot
,
from
,
to
);
if
(
second
>
to
)
{
pivot
=
selectPivot
(
from
,
to
);
pivot
=
data
[
to
];
second
=
partition
(
pivot
,
from
,
to
);
if
(
second
>
to
)
{
second
--;
}
}
quicksort
(
from
,
second
-
1
);
from
=
second
;
}
}
/**
* Sort a block using the binary insertion sort algorithm.
*
* @param from the index of the first entry to sort
* @param to the index of the last entry to sort
*/
private
void
binaryInsertionSort
(
int
from
,
int
to
)
{
for
(
int
i
=
from
+
1
;
i
<=
to
;
i
++)
{
T
x
=
data
[
i
];
int
ins
=
binarySearch
(
x
,
from
,
i
-
1
);
for
(
int
j
=
i
-
1
;
j
>=
ins
;
j
--)
{
data
[
j
+
1
]
=
data
[
j
];
}
data
[
ins
]
=
x
;
}
}
/**
* Find the index of the element that is larger than x.
*
* @param x the element to search
* @param from the index of the first entry
* @param to the index of the last entry
* @return the position
*/
private
int
binarySearch
(
T
x
,
int
from
,
int
to
)
{
while
(
from
<=
to
)
{
int
m
=
(
from
+
to
)
>>>
1
;
if
(
comp
.
compare
(
x
,
data
[
m
])
>=
0
)
{
from
=
m
+
1
;
}
else
{
to
=
m
-
1
;
}
}
return
from
;
}
/**
* Move all elements that are bigger than the pivot to the end of the list,
* and return the partitioning index. The partitioning index is the start
* index of the range where all elements are larger than the pivot. If the
* partitioning index is larger than the 'to' index, then all elements are
* smaller or equal to the pivot.
*
* @param pivot the pivot
* @param from the index of the first element
* @param to the index of the last element
* @return the the first element of the second partition
*/
private
int
partition
(
T
pivot
,
int
from
,
int
to
)
{
if
(
to
-
from
<
temp
.
length
)
{
return
partitionSmall
(
pivot
,
from
,
to
);
}
int
m
=
(
from
+
to
+
1
)
/
2
;
int
m1
=
partition
(
pivot
,
from
,
m
-
1
);
int
m2
=
partition
(
pivot
,
m
,
to
);
swapBlocks
(
m1
,
m
,
m2
-
1
);
return
m1
+
m2
-
m
;
}
/**
* Partition a small block using the temporary array. This will speed up partitioning.
*
* @param pivot the pivot
* @param from the index of the first element
* @param to the index of the last element
* @return the the first element of the second partition
*/
private
int
partitionSmall
(
T
pivot
,
int
from
,
int
to
)
{
int
tempIndex
=
0
,
dataIndex
=
from
;
for
(
int
i
=
from
;
i
<=
to
;
i
++)
{
T
x
=
data
[
i
];
if
(
comp
.
compare
(
x
,
pivot
)
<=
0
)
{
if
(
tempIndex
>
0
)
{
data
[
dataIndex
]
=
x
;
}
dataIndex
++;
}
else
{
temp
[
tempIndex
++]
=
x
;
}
}
if
(
tempIndex
>
0
)
{
System
.
arraycopy
(
temp
,
0
,
data
,
dataIndex
,
tempIndex
);
}
return
dataIndex
;
}
/**
* Swap the elements of two blocks in the data array. Both blocks are next
* to each other (the second block starts just after the first block ends).
*
* @param from the index of the first element in the first block
* @param second the index of the first element in the second block
* @param to the index of the last element in the second block
*/
private
void
swapBlocks
(
int
from
,
int
second
,
int
to
)
{
int
len1
=
second
-
from
,
len2
=
to
-
second
+
1
;
if
(
len1
==
0
||
len2
==
0
)
{
return
;
}
if
(
len1
<
temp
.
length
)
{
System
.
arraycopy
(
data
,
from
,
temp
,
0
,
len1
);
System
.
arraycopy
(
data
,
second
,
data
,
from
,
len2
);
System
.
arraycopy
(
temp
,
0
,
data
,
from
+
len2
,
len1
);
return
;
}
else
if
(
len2
<
temp
.
length
)
{
System
.
arraycopy
(
data
,
second
,
temp
,
0
,
len2
);
System
.
arraycopy
(
data
,
from
,
data
,
from
+
len2
,
len1
);
System
.
arraycopy
(
temp
,
0
,
data
,
from
,
len2
);
return
;
}
reverseBlock
(
from
,
second
-
1
);
reverseBlock
(
second
,
to
);
reverseBlock
(
from
,
to
);
}
/**
* Reverse all elements in a block.
*
* @param from the index of the first element
* @param to the index of the last element
*/
private
void
reverseBlock
(
int
from
,
int
to
)
{
while
(
from
<
to
)
{
T
old
=
data
[
from
];
data
[
from
++]
=
data
[
to
];
data
[
to
--]
=
old
;
}
}
/**
* Select a pivot. To ensure a good pivot is select, the median element of a
* sample of the data is calculated.
*
* @param from the index of the first element
* @param to the index of the last element
* @return the pivot
*/
private
T
selectPivot
(
int
from
,
int
to
)
{
int
count
=
(
int
)
(
6
*
Math
.
log10
(
to
-
from
));
count
=
Math
.
min
(
count
,
temp
.
length
);
int
step
=
(
to
-
from
)
/
count
;
for
(
int
i
=
from
,
j
=
0
;
i
<
to
;
i
+=
step
,
j
++)
{
temp
[
j
]
=
data
[
i
];
}
T
pivot
=
select
(
temp
,
0
,
count
-
1
,
count
/
2
);
return
pivot
;
}
/**
* Select the kth smallest element.
*
* @param data the array
* @param from the index of the first element
* @param to the index of the last element
* @param k which element to return
* @return the kth smallest element
*/
private
T
select
(
T
[]
data
,
int
from
,
int
to
,
int
k
)
{
while
(
true
)
{
int
pivotIndex
=
(
to
+
from
)
>>>
1
;
int
pivotNewIndex
=
selectPartition
(
data
,
from
,
to
,
pivotIndex
);
int
pivotDist
=
pivotNewIndex
-
from
+
1
;
if
(
pivotDist
==
k
)
{
return
data
[
pivotNewIndex
];
}
else
if
(
k
<
pivotDist
)
{
to
=
pivotNewIndex
-
1
;
}
else
{
k
=
k
-
pivotDist
;
from
=
pivotNewIndex
+
1
;
}
}
}
/**
* Partition the elements to select the kth element.
*
* @param data the array
* @param from the index of the first element
* @param to the index of the last element
* @param pivotIndex the index of the pivot
* @return the new index
*/
private
int
selectPartition
(
T
[]
data
,
int
from
,
int
to
,
int
pivotIndex
)
{
T
pivotValue
=
data
[
pivotIndex
];
swap
(
data
,
pivotIndex
,
to
);
int
storeIndex
=
from
;
for
(
int
i
=
from
;
i
<=
to
;
i
++)
{
if
(
comp
.
compare
(
data
[
i
],
pivotValue
)
<
0
)
{
swap
(
data
,
storeIndex
,
i
);
storeIndex
++;
}
}
swap
(
data
,
to
,
storeIndex
);
return
storeIndex
;
}
/**
* Swap two elements in the array.
*
* @param data the array
* @param a the index of the first element
* @param b the index of the second element
*/
private
void
swap
(
T
[]
data
,
int
a
,
int
b
)
{
T
temp
=
data
[
a
];
data
[
a
]
=
data
[
b
];
data
[
b
]
=
temp
;
}
}
This diff is collapsed.
Click to expand it.
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论