首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Timsort是如何按降序处理数据的?

Timsort是如何按降序处理数据的?
EN

Stack Overflow用户
提问于 2013-12-01 11:39:13
回答 1查看 780关注 0票数 7

来自:

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的“好”情况。

实际上,JDK files/new/src/share/classes/java/util/TimSort.java中的files/new/src/share/classes/java/util/TimSort.java有一个方法"countRunAndMakeAscending“。

代码语言:javascript
复制
@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;
}

为什么不以另一种方式实施:

代码语言:javascript
复制
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;
}

所以它会在非上升秩序下正常工作吗?

EN

回答 1

Stack Overflow用户

发布于 2013-12-09 16:00:55

是。

基本上,它决定“上升”实际上意味着“不下降”,没有任何一般性的损失--如果你有5,5,4,3,它只会在下一次呼叫中将它分解为5,5,然后是4,3

至于为什么,我想这是为了简单起见:只需在代码中和原始版本中计算reverseRange()调用的次数,您就会得到这个想法(我注意到理解一个版本比另一个版本花了多长时间:)

编辑:错误,错误,错误!正如奥斯卡·史密斯( Oscar Smith )所指出的,原因在于使时间排序成为一种稳定的排序算法。如果有人知道如何转移不应得的赏金..。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/20311706

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档