view algs4-c++/src/RandomQueue.hpp @ 19:60fb85712482

Problems 1.3.35 and 36
author Eris Caffee <discordia@eldalin.com>
date Mon, 22 Jun 2015 14:07:01 -0500
parents
children
line source
1 #ifndef RANDOMQUEUE_HPP
2 #define RANDOMQUEUE_HPP
4 #include <algorithm>
5 #include <cassert>
6 #include <cstddef>
7 #include <chrono>
8 #include <random>
9 #include <vector>
11 template <typename T>
12 class RandomQueue {
14 public:
16 ////////////////////////////////////////
17 class iterator {
19 public:
21 iterator( RandomQueue<T> *q, size_t c, size_t e );
23 iterator& operator++();
24 iterator operator++(int);
26 T operator*();
27 bool operator!=( typename RandomQueue<T>::iterator );
29 private:
31 RandomQueue<T> *queue;
32 size_t curr;
33 size_t end;
34 };
36 ////////////////////////////////////////
37 RandomQueue( void );
38 ~RandomQueue( void );
40 void enqueue( T &item );
41 T dequeue( void );
42 T sample( void );
44 bool is_empty( void );
45 size_t size( void );
47 iterator begin( void );
48 iterator end( void );
50 private:
52 size_t N;
53 size_t max;
54 T *data;
55 std::vector<size_t> order;
57 void resize( size_t new_max );
58 size_t sample_index( void );
59 void get_order( void );
60 };
63 ////////////////////////////////////////////////////////////////////////////////
65 template <typename T>
66 RandomQueue<T>::RandomQueue( void ) :
67 N (0),
68 max(1) {
69 data = new T[2];
70 }
72 template <typename T>
73 RandomQueue<T>::~RandomQueue( void ) {
74 assert( N == 0 ); // Catch the potential memory leak.
75 if ( data )
76 delete[] data;
77 }
79 template <typename T>
80 void RandomQueue<T>::enqueue( T &item ) {
81 if ( N == max )
82 resize( 2 * max );
84 data[N] = item;
85 ++N;
86 }
88 template <typename T>
89 size_t RandomQueue<T>::sample_index( void ) {
90 unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
91 std::default_random_engine generator ( seed );
92 std::uniform_int_distribution<size_t> distribution( 0, N-1 );
93 return distribution(generator);
94 }
96 template <typename T>
97 T RandomQueue<T>::dequeue( void ) {
98 assert( N > 0 );
100 size_t i = sample_index();
102 T tmp = data[N-1];
103 data[N-1] = data[i];
104 data[i] = tmp;
106 T item = data[N-1];
108 --N;
110 return item;
111 }
113 template <typename T>
114 T RandomQueue<T>::sample( void ) {
115 assert( N > 0 );
117 size_t i = sample_index();
118 return data[i];
119 }
121 template <typename T>
122 bool RandomQueue<T>::is_empty( void ) {
123 return N == 0;
124 }
126 template <typename T>
127 size_t RandomQueue<T>::size( void ) {
128 return N;
129 }
131 template <typename T>
132 void RandomQueue<T>::resize( size_t new_max ) {
133 T *new_data = new T[new_max];
134 for ( size_t i = 0; i < N; ++i )
135 new_data[i] = data[i];
136 T *old_data = data;
137 data = new_data;
138 delete[] old_data;
139 max = new_max;
140 }
142 template <typename T>
143 void RandomQueue<T>::get_order( void ) {
144 for ( size_t i = 0; i < N; ++i )
145 order.push_back( i );
147 unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
148 shuffle (order.begin(), order.end(), std::default_random_engine(seed));
149 }
151 template <typename T>
152 typename RandomQueue<T>::iterator RandomQueue<T>::begin( void ) {
153 if ( order.size() != N )
154 get_order();
156 return RandomQueue<T>::iterator( this, 0, order.size() );
157 }
159 template <typename T>
160 typename RandomQueue<T>::iterator RandomQueue<T>::end( void ) {
161 if ( order.size() != N )
162 get_order();
164 return RandomQueue<T>::iterator( this, order.size(), order.size() );
165 }
168 ////////////////////////////////////////////////////////////////////////////////
170 template <typename T>
171 RandomQueue<T>::iterator::iterator( RandomQueue<T> *q, size_t c, size_t e ) :
172 queue (q),
173 curr (c),
174 end (e)
175 {
176 }
178 template <typename T>
179 typename RandomQueue<T>::iterator & RandomQueue<T>::iterator::operator++() {
180 if ( this->curr != this->end )
181 ++(this->curr);
182 return *this;
183 }
185 template <typename T>
186 typename RandomQueue<T>::iterator RandomQueue<T>::iterator::operator++( int ) {
187 auto t = RandomQueue<T>::iterator( *this );
189 if ( this->curr != this->end )
190 ++(this->curr);
192 return t;
193 }
195 template <typename T>
196 T RandomQueue<T>::iterator::operator*() {
198 return this->queue->data[ this->queue->order[ this->curr ] ];
199 }
201 template <typename T>
202 bool RandomQueue<T>::iterator::operator!=( typename RandomQueue<T>::iterator other ) {
203 return this->curr != other.curr;
204 }
207 #endif