【问题标题】:Algorithm to maintain a sorted (numerically) list of numbers (Doubles)预排序数字列表的算法
【发布时间】:2022-11-28 22:06:24
【问题描述】:

假设我正在使用 Math.random() 生成随机数,可能有 1000 个,并且我希望它们(始终)按升序排列。是否有某种数据结构可以让它们始终保持排序,而无需调用排序例程?我唯一能想到的就是堆?但可能有更好的方法。

一些代码会有所帮助:

const numContainer = {};

for(let i = 0; i < 1000; i++){
   const r = Math.random();
   numContainer[r] = {r};   // this isn't helping :-)
}

很明显,上面的内容并不会真正维护键等的任何数字顺序。我希望在我去的时候对它们进行排序。

【问题讨论】:

  • 我会使用二叉树。每次你有一个新数字时,你都会将它添加到正确的叶子上,这样你所有的数字都是有序的,而不是传统的数组方式。
  • B-tree,B+-tree,AVL,红黑,skiplist,...任你挑选。
  • booof 我想知道是否有线性方式
  • 你能更具体地说明你在做什么吗?你想用排序后的随机数做什么?请注意,对 1000 个随机数进行 1000 次排序几乎不需要时间,因此很难找到对现实世界有任何影响的“优化”解决方案。
  • 这回答了你的问题了吗? Random numbers external sort

标签: algorithm sorting data-structures heap


【解决方案1】:

heap 仅部分排序:节点仅根据其父节点排序。也许您正在考虑 binary search tree

自平衡二叉搜索树的典型实现是红黑树,它可以使用带有一些空格的数组来实现(如果有 n 个元素,则最多 n-2 个)。

整个操作仍然会在相同的时间内运行,在复杂性方面,就像填充一个数组并在最后对它进行排序一样,尽管我敢打赌后一个选项几乎总是更快。

【讨论】:

    【解决方案2】:

    您可以在线性时间内按排序顺序生成数字。描述如何执行此操作的论文是:Bentley & Saxe 生成随机数的排序列表

    https://pdfs.semanticscholar.org/2dbc/4e3f10b88832fcd5fb88d34b8fb0b0102000.pdf

    /**
     * Generate an sorted list of random numbers sorted from 1 to 0, given the size
     * of the list being requested.
     * 
     * This is an implementation of an algorithm developed by Bentley and Sax, and
     * published in in ACM Transactions on Mathematical Software (v6, iss3, 1980) on
     * 'Generating Sorted Lists of Random Numbers'.
     */
    public class SortedRandomDoubleGenerator {
        private long       valsFound;
        private double     curMax;
        private final long numVals;
    
        /**
         * Instantiate a generator of sorted random doubles.
         * 
         * @param numVals the size of the list of sorted random doubles to be
         *        generated
         */
        public SortedRandomDoubleGenerator(long numVals) {
            curMax = 1.0;
            valsFound = 0;
            this.numVals = numVals;
        }
    
        /**
         * @return the next random number, in descending order.
         */
        public double getNext() {
            curMax = curMax
                    * Math.pow(Math.E, Math.log(RandomNumbers.nextDouble())
                            / (numVals - valsFound));
            valsFound++;
            return curMax;
        }
    }
    

    【讨论】:

    • ^^ 代码是按降序排列的,但是你可以很容易地修改。例如,返回 (1.0 - curMax) 而不是返回 curMax。我将其发布为对一个不同但非常相似的问题的回答:stackoverflow.com/questions/46058304/…。在这种情况下不确定是关闭重复还是发布答案更好。
    【解决方案3】:

    您没有对数据结构指定任何约束,因此基本解决方案是一个数组,并结合了新元素的插入。

    或者链表。

    或二叉搜索树。

    不是一堆!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-23
      • 2016-05-07
      相关资源
      最近更新 更多