从Java中最小最小的排序列表

时间:2015-04-24 15:51:15

标签: java algorithm sorting probability-density

我正在尝试对一组数据进行排序,使其看起来像是概率分布函数的直方图(我假设目前正态分布)。

我有一个条目列表:

private static final class SortableDatasetEntry{
    Number value;
    Comparable key;
    public SortableDatasetEntry(Number value, Comparable key){
      this.value = value;
      this.key = key;
    }
}

一个例子: 我有这些项目:{1,2,3,4,5,6,7,8,9}

编辑: 我想要的排序列表:{1,3,5,7,9,8,6,4,2}(或类似的东西)数字并不总是那么整洁(即简单地按奇数/偶数排序也不会)。我有一个部分解决方案,涉及按常规顺序(从最低到最高)排序,然后通过每次插入到中间将该列表复制到另一个,因此插入的最后一个项目(到中间)是最大的。我还是想找一个用比较器做这个的方法。

这非常棘手,因为它没有按value的绝对值排序,而是按照集合中的均值(value)的距离进行排序,然后以某种方式移动了这些值最接近平均值的是居中。我知道compareTo函数必须是“可逆的”(我忘了正确的术语)。

奖励积分:如何确定数据的正确分布(即,如果假设不正常)。

6 个答案:

答案 0 :(得分:1)

首先计算均值并将其存储在名为mean的变量中。接下来,当您将条目插入SortableDatasetEntry时,请使用value - mean作为每个条目的实际值,而不是value

答案 1 :(得分:0)

对于我所看到的,你可能想得到一个“平均距离”元组,值并用第一个条目“平均距离”对元组列表进行排序。

答案 2 :(得分:0)

您会发现将直方图构建为 @property(nonatomic, readonly) NSTimeInterval playableDuration 更容易。

Map

请注意Histogram

的意图
  

要构建直方图,第一步是“对”值范围进行“bin” - 即将整个值范围划分为一系列小间隔 - 然后计算每个间隔中落入的值。

答案 3 :(得分:0)

会是这样的:

 public List<Integer> customSort(List<Integer> list) {
    Collections.sort(list);
    List<Integer> newList = new ArrayList<Integer>();
    for (int i = 0; i < list.size(); i += 2) {
        newList.add(list.get(i));
    }
    if (list.size() % 2 == 0) {
        for (int i = 1; i < list.size(); i += 2) {
            newList.add(list.get(list.size() - i));
        }
    } else {
        for (int i = 1; i < list.size(); i += 2) {
            newList.add(list.get(list.size() - i - 1));
        }
    }
    return newList;
}

工作?我输入{1,2,3,4,5,6,7,8,9}并获得{1,3,5,7,9,8,6,4,2}{1,2,3,4,5,6,7,8}提供{1,3,5,7,8,6,4,2}

答案 4 :(得分:0)

仅使用自定义Comparator,您无法在单一种类中完成此操作。

但是,就地仍然是可行的,没有额外的参考集合。

您当前的方法不是就地,但可能是最容易实现和理解的方法。除非内存中的集合大小是一个问题,否则请考虑使用当前的方法。

单一排序的自定义比较器

您所需的订单取决于升序。鉴于未分类的数据,您的Comparator在第一次排序时没有升序。

就地方法

您可以就地创建所需的订单。

以下假设基于0的指数。

一种方法可以使用两种方法。首先,按升序排序。用索引标记每个对象。在第二种比较器中,具有偶数索引的所有对象将小于具有奇数索引的所有对象。具有偶数索引的对象将按升序排序。具有奇数索引的对象将按降序排序。

另一种方法是自定义排序算法,支持从虚拟索引到物理索引的映射。排序算法将在虚拟索引空间中创建升序。您的索引映射将按照您希望的顺序在物理内存中进行布局。这是一个未经测试的索引映射草图:

private int mapVirtualToPhysical( int virtualIndex, int countElements ) {
    boolean isEvenIndex = ( 0 == (index % 2));
    int physicalIndex = isEvenIndex ? (index / 2) : (countElements - (index/2) - 1);
    return physicalIndex;
}

这些中的任何一个都优先是初始排序,然后是O(n)系列的掉期。但是,我还没有确定掉期顺序。到目前为止,我提出的最佳方法是按顺序获得左尾,但右尾要么需要后续排序,要么堆栈。

答案 5 :(得分:0)

对于大型数据集,您可以在SortableEntry构造函数确定时使用该方法,使用随机数生成器确定此特定条目将占用的图表的哪一侧(最左侧或右侧):

static final class SortableEntry<T>{

    Number value;
    Comparable<T> key;
    int hr;
    static Random rnd = new Random();

    public SortableEntry(Number value, Comparable<T> key){
        this.value = value;
        this.key = key;
        this.hr = rnd.nextInt(2) == 0 ? -1 : 1;  // here
    }
}

额外hr变量的要点是使任何&#34;对&#34;进入大于任何&#34;左&#34;反之亦然。如果两个比较条目中的hr相同,请按实际key进行比较,同时考虑hr的符号:

static final class SortableEntryComparator<T> implements Comparator<SortableEntry<T>> {

    @Override
    public int compare(SortableEntry<T> e1, SortableEntry<T> e2) {
        if (e1.hr == e2.hr) 
            return e1.hr < 0 ? e1.key.compareTo((T) e2.key) : e2.key.compareTo((T) e1.key);
        else 
            return e1.hr - e2.hr;
    }
}

现在进行一项小测试:

@Test
public void testSort() {
    List<Integer> keys = Arrays.asList(10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 
                                       12, 25, 31, 33, 34, 36, 39, 41, 26, 49,
                                       52, 52, 58, 61, 63, 69, 74, 83, 92, 98);
    List<SortableEntry<Integer>> entries = new ArrayList<>();
    for (Integer k : keys) {
        entries.add(new SortableEntry<Integer>(0, k)); 
    }
    entries.sort(new SortableEntryComparator<Integer>());
    System.out.println(entries);
}
// output: 
// [12, 26, 33, 36, 39, 40, 49, 50, 52, 60, 61, 63, 80, 90, 98, 100, 92, 83, 74, 70, 69, 58, 52, 41, 34, 31, 30, 25, 20, 10]
// the highest key (100) is not precisely in the center,
// but it will tend to occur in the center when dataset is large.