1,807 次浏览

C# 乱序算法

.NET 默认没有提供乱序算法,不过我们可以使用 OrderBy 方法进行实现,如下所示。

var data = Enumerable.Range(1, 1000);

var query = data.OrderBy(i => Guid.NewGuid());

foreach (var i in query)
{
    Console.Write($"{i} ");
}

data.OrderBy(i => Guid.NewGuid()); 即可,不过这种方式的效率和时间复杂度并不是最优的,你可以查看这里做进一步了解:

Is using Random and OrderBy a good shuffle algorithm?


而在 Java 中,可以使用 Collections.shuffle()

public class Collections {
    private static Random r;
    private static final int SHUFFLE_THRESHOLD        =    5;
    
    public static void shuffle(List<?> list) {
        if (r == null) {
            r = new Random();
        }
        shuffle(list, r);
    }
    
    public static void shuffle(List<?> list, Random rnd) {
        int size = list.size();
        if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {
            for (int i = size; i > 1; i--)
                swap(list, i - 1, rnd.nextInt(i));
        } else {
            Object arr[] = list.toArray();

            // Shuffle array
            for (int i = size; i > 1; i--)
                swap(arr, i - 1, rnd.nextInt(i));

            // Dump array back into list
            ListIterator it = list.listIterator();
            for (int i = 0; i < arr.length; i++) {
                it.next();
                it.set(arr[i]);
            }
        }
    }
    
    public static void swap(List<?> list, int i, int j) {
        final List l = list;
        l.set(i, l.set(j, l.get(i)));
    }
    
    private static void swap(Object[] arr, int i, int j) {
        Object tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
    
}

C++ 则可以使用 STL 函数 random_shuffle()

template <class RandomAccessIterator, class RandomNumberGenerator>
  void random_shuffle (RandomAccessIterator first, RandomAccessIterator last,
                       RandomNumberGenerator& gen)
{
  iterator_traits<RandomAccessIterator>::difference_type i, n;
  n = (last-first);
  for (i=n-1; i>0; --i) {
    swap (first[i],first[gen(i+1)]);
  }
}

About nista

THERE IS NO FATE BUT WHAT WE MAKE.

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注