经典的Fisher-Yates Shuffle算法
回头看酷壳上那篇《一些有意思的算法代码》,在清单上看到第一条是Binomial Heap,回想一下好像是算法导论里刚刚研习过的内容,对,是二项堆,特别想看看具体的实现,点开链接看到满满的注释,顿时幸福洋溢。再看作者,Keith Schwarz,他是一个斯坦福大学计算机科学系的讲师,在自己的网站放了一些自己实现的算法和数据结构,觉得挺好的,有空可以去看看,这是链接:http://www.keithschwarz.com/interesting/。
改天再谈谈二项堆的内容,今天先贴一个应该是其中最短的代码,Random Shuffle随机洗牌,随便学习一下算法和C++。(这位老师还非常愿意分享自己的代码,只是注满注释的代码显得太长了)
代码注释很多也很浅显,就不翻译了。虽说核心的代码就两行,但是里面的所有内容还是很应该学习的,比如,可以在自选范围内进行随机排列,可以传入自定义的随机数产生算法,使用了模板这样任何数据类型都可以进行排列。这个算法核心的意思也就一句话来概括:随机选取一个数组元素,和第一个元素进行交换,然后继续按照这种方法处理剩下的数组元素,只需要线性时间和常量空间即可。
这里面还有一点没有想到的是,在函数参数列表里居然可以传入函数名称,然后在里面执行这个传入的函数,难道是函数指针,C++真是忘得差不多了。
==================================================================================
/**************************************************************************
* File: RandomShuffle.hh
* Author: Keith Schwarz (htiek@cs.stanford.edu)
*
* An implemention of a function for randomly permuting the elements of a
* sorted range. The algorithm is an implementation of the Fisher-Yates
* shuffle (also called the Knuth shuffle), which works by randomly selecting
* an element from the the array and swapping it to the front, then recursively
* repeating the process on the rest of the array. It runs in linear time
* and with only constant space.
*
* This implementation, by default, works using the system rand function,
* which is not ideal if cryptographic randomness is desired. Consequently,
* like the STL algorithm random_shuffle, the algorithm allows for a custom
* random generator to be passed into the function.
*/
#ifndef RandomShuffle_Included
#define RandomShuffle_Included
#include <algorithm> // For iter_swap
#include <cstdlib> // For rand
/**
* Function: RandomShuffle(RandomIterator begin, RandomIterator end);
* ------------------------------------------------------------------------
* Randomly permutes the elements in the range [begin, end), using the system
* rand function as a source of randomness.
*/
template <typename RandomIterator>
void RandomShuffle(RandomIterator begin, RandomIterator end);
/**
* Function: RandomShuffle(RandomIterator begin, RandomIterator end,
* RandomGenerator rng);
* ------------------------------------------------------------------------
* Randomly permutes the elements in the range [begin, end), using the
* provided callback as a source of randomness. The generator should be
* callable as a nullary function which produces a uniformly-distributed
* random value over a range at least as large as the input range.
*/
template <typename RandomIterator, typename RandomGenerator>
void RandomShuffle(RandomIterator begin, RandomIterator end,
RandomGenerator rnd);
/* * * * * Implementation Below This Point * * * * */
/* Main implementation of the algorithm. */
template <typename RandomIterator, typename RandomGenerator>
void RandomShuffle(RandomIterator begin, RandomIterator end,
RandomGenerator rnd) {
/* Iterate across the elements, picking a random element and swapping it
* to the front at each step.
*/
for (RandomIterator itr = begin; itr != end; ++itr)
std::iter_swap(itr, itr + rnd() % (end - itr));
}
/* Default implementation just uses rand. */
template <typename RandomIterator>
void RandomShuffle(RandomIterator begin, RandomIterator end) {
RandomShuffle(begin, end, std::rand);
}
#endif
==================================================================================