随机播放算法算法

2023-09-11 22:36:46 作者:清新优雅的:半城烟雨〞半城雾

我需要从一个范围(例如,从X到Y)以随机的顺序创建号码列表,使每一个订单都有平等的机会。

I need to create a list of numbers from a range (for example from x to y) in a random order so that every order has an equal chance.

我需要这样一个音乐播放器,我写在C#中,以随机顺序创建播放列表。

I need this for a music player I write in C#, to create play lists in a random order.

任何想法?

感谢。

编辑:我不感兴趣,改变原有的列表中,随便挑了从一系列随机指标随机顺序,使每一笔订单都有一个平等的机会。

I'm not interested in changing the original list, just pick up random indexes from a range in a random order so that every order has an equal chance.

下面是我到目前为止已经wrriten:

Here's what I've wrriten so far:

    public static IEnumerable<int> RandomIndexes(int count)
    {
        if (count > 0)
        {
            int[] indexes = new int[count];
            int indexesCountMinus1 = count - 1;

            for (int i = 0; i < count; i++)
            {
                indexes[i] = i;
            }

            Random random = new Random();

            while (indexesCountMinus1 > 0)
            {
                int currIndex = random.Next(0, indexesCountMinus1 + 1);
                yield return indexes[currIndex];

                indexes[currIndex] = indexes[indexesCountMinus1];
                indexesCountMinus1--;
            }

            yield return indexes[0];
        }
    }

它的工作,但这样做的唯一的问题是我需要分配的内存中的数组中的计数的大小。我在寻找的东西剂量不需要内存分配。

It's working, but the only problem of this is that I need to allocate an array in the memory in the size of count. I'm looking for something that dose not require memory allocation.

感谢。

推荐答案

这其实是可以棘手,如果你不小心(即使用的幼稚的洗牌算法)。看看在费雪耶茨/克努特洗牌算法获得价值合理分配。

This can actually be tricky if you're not careful (i.e., using a naïve shuffling algorithm). Take a look at the Fisher-Yates/Knuth shuffle algorithm for proper distribution of values.

一旦你的洗牌算法,其余的应该很容易。

Once you have the shuffling algorithm, the rest should be easy.

下面是从杰夫·阿特伍德详细。

Here's more detail from Jeff Atwood.

最后,这里是全碟的implementation和描述。

修改

我不相信有一个解决方案,满足你的两个相互矛盾的需求(第一,是随机的,没有重复,二来没有分配任何额外的内存)。我相信你可能是prematurely优化的解决方案,可以对内存的影响可以忽略不计,除非你嵌入。或者,也许我只是没有足够聪明,想出了一个答案。

I don't believe that there's a solution that satisfies your two conflicting requirements (first, to be random with no repeats and second to not allocate any additional memory). I believe you may be prematurely optimizing your solution as the memory implications should be negligible, unless you're embedded. Or, perhaps I'm just not smart enough to come up with an answer.

就这样,这里的code,这将创建一个使用高德纳 - 费雪耶茨算法(与稍作修改)均匀分布的随机指标的数组。您可以缓存结果数组,或执行任何数量取决于你的执行的其他优化。

With that, here's code that will create an array of evenly distributed random indexes using the Knuth-Fisher-Yates algorithm (with a slight modification). You can cache the resulting array, or perform any number of optimizations depending on the rest of your implementation.

  private static int[] BuildShuffledIndexArray( int size ) {

     int[] array = new int[size];
     Random rand = new Random();
     for ( int currentIndex = array.Length - 1; currentIndex > 0; currentIndex-- ) {
        int nextIndex = rand.Next( currentIndex + 1 );
        Swap( array, currentIndex, nextIndex );
     }
     return array;
  }

  private static void Swap( IList<int> array, int firstIndex, int secondIndex ) {

     if ( array[firstIndex] == 0 ) {
        array[firstIndex] = firstIndex;
     }
     if ( array[secondIndex] == 0 ) {
        array[secondIndex] = secondIndex;
     }
     int temp = array[secondIndex];
     array[secondIndex] = array[firstIndex];
     array[firstIndex] = temp;
  }

注意:您可以使用 USHORT 而不是 INT 到一半的大小内存只要你没有超过65535项的播放列表。你总是可以通过编程切换到 INT 如果大小超过 ushort.MaxValue 。如果我个人而言,增加了超过65K的项目到播放列表中,我就不会被存储利用率提高惊呆了。

NOTE: You can use ushort instead of int to half the size in memory as long as you don't have more than 65,535 items in your playlist. You could always programmatically switch to int if the size exceeds ushort.MaxValue. If I, personally, added more than 65K items to a playlist, I wouldn't be shocked by increased memory utilization.

请记住,这是一个管理的语言。虚拟机将一直保留更多的内存比您正在使用限制的次数就需要问操作系统更多的RAM和限制碎片。

Remember, too, that this is a managed language. The VM will always reserve more memory than you are using to limit the number of times it needs to ask the OS for more RAM and to limit fragmentation.

修改

好了,最后一次尝试:我们可以看一下调整性能/内存权衡:你的可以的创建整数列表,然后把它写入到磁盘中。然后,只需保持一个指针偏移的文件中。然后,每次你需要一个新的号码时,你只需要磁盘I / O处理。也许你可以找到一些平衡在这里,只是读的 N 的数据-sized块到内存中的 N 的是一些数字你满意。

Okay, last try: we can look to tweak the performance/memory trade off: You could create your list of integers, then write it to disk. Then just keep a pointer to the offset in the file. Then every time you need a new number, you just have disk I/O to deal with. Perhaps you can find some balance here, and just read N-sized blocks of data into memory where N is some number you're comfortable with.

好像很多的洗牌算法的工作,但对节约内存,如果你死了设置,那么至少它是一个选项。

Seems like a lot of work for a shuffle algorithm, but if you're dead-set on conserving memory, then at least it's an option.