Reservior Sampling

Problem

Take k elements at random from a stream of unknown or infinite or unknown length n in O(n)

Solution

  1. Fill up a reserviour of size k using the first k readings from the stream
  2. Read the next element
  3. Continue until the end of the stream is reached or you get board.

  4. Note: Since we replace a value at random, the order of samples in the reservoir is unlikely to match the order of samples in the stream. In cases where this matters it is a simple matter to store the current value of n with the sample.

Code

    class ReserviorSampling<T>
    {
        private int samplesReadSoFar = 0;
        private Random r = new Random();
        public T[] Samples;
        public int SamplesWanted { getprivate set; }
 
        public ReserviorSampling(int samplesWanted)
        {
            this.Samples = new T[samplesWanted];
            this.SamplesWanted = samplesWanted;
        }
 
        public void Add(T sample)
        {
            if (samplesReadSoFar < this.SamplesWanted)
            {
                this.Samples[this.samplesReadSoFar] = sample;
            }
            else if (r.NextDouble() < (this.SamplesWanted / (doublethis.samplesReadSoFar))
            {
                this.Samples[r.Next(this.SamplesWanted)] = sample;
            }
            this.samplesReadSoFar++;
        }
    }