来自:
http://svn.python.org/projects/python/trunk/Objects/listsort.txt
和
http://en.wikipedia.org/wiki/Timsort
我知道,Timsort在a0 > a1 > a2 > ...
时有一些优化,但下一个数组怎么样:
10000,10000,9999,9999,9998,9998,....,9,9,8,8,7,7,6,6,5,5,4,4,3,3,2,2,1,1,0,0
这种阵列的时间效率是多少?
(整数用于简化示例,需要稳定排序) 我做了一些测量,似乎这样的阵列对于Timsort来说不是“好”的情况。
实际上,JDS中的TimSort http://cr.openjdk.java.net/~martin/webrevs/openjdk7/timsort/raw_files/new/src/share/classes/java/util/TimSort.java 有一个方法“countRunAndMakeAscending”
@SuppressWarnings("unchecked")
private static int countRunAndMakeAscending(Object[] a, int lo, int hi) {
assert lo < hi;
int runHi = lo + 1;
if (runHi == hi)
return 1;
// Find end of run, and reverse range if descending
if (((Comparable) a[runHi++]).compareTo(a[lo]) < 0) { // Descending
while(runHi < hi && ((Comparable) a[runHi]).compareTo(a[runHi - 1]) < 0)
runHi++;
reverseRange(a, lo, runHi);
} else { // Ascending
while (runHi < hi && ((Comparable) a[runHi]).compareTo(a[runHi - 1]) >= 0)
runHi++;
}
return runHi - lo;
}
为什么不以另一种方式实现它:
private static int countRunAndMakeAscending(Object[] a, int lo, int hi) {
int runHi = lo;
int lastEqual = lo;
int ascending = 0;
while (++runHi < hi) {
int c = ((Comparable) a[runHi+1]).compareTo(a[runHi]);
if (ascending == 0) {
if (c != 0) {
if (c > 0) {
ascending = 1;
} else {
ascending = -1;
reverseRange(a, lastEqual, runHi);
lastEqual = runHi;
}
}
} else if (ascending == 1) {
if (c < 0) {
return runHi - lo;
}
} else {
if (c > 0) {
reverseRange(a, lastEqual, runHi);
reverseRange(a, lo, runHi);
return runHi - lo;
} else if (c < 0) {
reverseRange(a, lastEqual, runHi);
lastEqual = runHi;
}
}
}
if (ascending == -1) {
reverseRange(a, lastEqual, runHi);
reverseRange(a, lo, runHi);
}
return runHi - lo;
}
所以它会以非递增顺序正常工作吗?
答案 0 :(得分:2)
是
基本上它决定&#34;提升&#34;真的意思是&#34;没有下降&#34;,没有任何一般性的损失 - 如果你有例如[5,5,4 3]它只会将其分解为[5,5](升序)然后[4 ,3](降序)在下次通话中。
至于为什么,我认为这是为了简单:只需尝试计算代码和原始版本中reverseRange()
的调用次数,然后你就可以了解它(我得到了它)通过注意我理解一个版本与另一个版本相比花了多长时间:))
编辑:错误错误!正如奥斯卡史密斯指出的那样,原因是让timsort成为稳定的排序算法。 如果有人知道如何转移不应得的赏金......