PageRenderTime 13ms CodeModel.GetById 1ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/data/heap.d

http://github.com/wilkie/djehuty
D | 207 lines | 137 code | 44 blank | 26 comment | 25 complexity | 5e01117bb41059768e0c020879318c3a MD5 | raw file
  1/*
  2 * priorityqueue.d
  3 *
  4 * A simple implementation of a priority queue (a min-heap or a max-heap).
  5 * References are stored with an array indexed at 1. Implementation is a sorted heap.
  6 *
  7 * Author: Dave Wilkinson
  8 * Originated: November 7th, 2009
  9 *
 10 */
 11
 12module data.heap;
 13
 14import data.list;
 15
 16import core.util;
 17
 18enum : bool {
 19	MinHeap = true,
 20	MaxHeap = false
 21}
 22
 23interface HeapInterface(T, bool minHeap = MinHeap) {
 24	template add(R) {
 25		void add(R item);
 26	}
 27
 28	T remove();
 29
 30	void clear();
 31	bool empty();
 32
 33	size_t length();
 34}
 35
 36class PriorityQueue(T, bool minHeap = MinHeap) : HeapInterface!(T, minHeap) {
 37
 38	this() {
 39		_length = 0;
 40	}
 41
 42	template add(R) { 
 43		void add(R item) {
 44
 45			// determine location for data:
 46			size_t idx = _length + 1;
 47
 48			// check for bounds
 49			while (idx >= _data.length) {
 50				_resize();
 51			}
 52
 53			// add data:
 54
 55			static if (IsArray!(R)) {
 56				_data[idx] = item.dup;
 57			}
 58			else {
 59				_data[idx] = cast(T)item;
 60			}
 61
 62			_length++;
 63
 64			// bubble data up:
 65			_bubbleUp(idx);
 66		}
 67	}
 68
 69	T remove() {
 70		T ret;
 71
 72		if (empty()) {
 73			// XXX: Throw Tree Exception
 74			return ret;
 75		}
 76
 77		ret = _data[1];
 78
 79		// take last item, place at root:
 80		_data[1] = _data[_length];
 81		_length--;
 82
 83		// bubble data down:
 84		_bubbleDown(1);
 85
 86		// return saved temp
 87		return ret;
 88	}
 89
 90	T peek() {
 91		T ret;
 92
 93		if (empty()) {
 94			// XXX: Throw Tree Exception
 95			return ret;
 96		}
 97
 98		return _data[1];
 99	}
100
101	bool empty() {
102		return _length == 0;
103	}
104
105	void clear() {
106		_length = 0;
107		_data = null;
108	}
109
110	size_t length() {
111		return _length;
112	}
113
114protected:
115
116	void _bubbleUp(size_t idx) {
117		if (idx <= 1) {
118			// base case
119			return;
120		}
121
122		// get the parent, note the array is indexed at 1
123		size_t parent = idx >> 1;
124
125		// compare
126		static if (minHeap) {
127			if (_data[parent] > _data[idx]) {
128				_swap(parent, idx);
129				_bubbleUp(parent);
130			}
131		}
132		else {
133			if (_data[parent] < _data[idx]) {
134				_swap(parent, idx);
135				_bubbleUp(parent);
136			}
137		}
138	}
139
140	void _bubbleDown(size_t idx) {
141		if (idx >= _length + 1) {
142			// base case
143			return;
144		}
145
146
147		size_t idx1, idx2, bestIdx;
148
149		idx1 = idx << 1;
150		idx2 = idx1 + 1;
151
152		if (idx1 >= _length + 1) {
153			// base case
154			return;
155		}
156
157		// compare idx1 and idx2
158		bestIdx = idx1;
159
160		if (idx2 <= _length) {
161			static if (minHeap) {
162				if (_data[idx1] > _data[idx2]) {
163					bestIdx = idx2;
164				}
165			}		
166			else {
167				if (_data[idx1] < _data[idx2]) {
168					bestIdx = idx2;
169				}
170			}
171		}
172
173		// compare idx and bestIdx
174		static if (minHeap) {
175			if (_data[bestIdx] < _data[idx]) {
176				_swap(bestIdx, idx);
177				_bubbleDown(bestIdx);
178			}
179		}
180		else {
181			if (_data[bestIdx] > _data[idx]) {
182				_swap(bestIdx, idx);
183				_bubbleDown(bestIdx);
184			}
185		}
186	}
187
188	void _swap(size_t idx1, size_t idx2) {
189		T tmp = _data[idx1];
190		_data[idx1] = _data[idx2];
191		_data[idx2] = tmp;
192	}
193
194	void _resize() {
195		T[] temp = _data;
196		if (_data.length == 0) {
197			_data = new T[10];
198		} 
199		else {
200			_data = new T[_data.length * 2];
201		}
202		_data[0..temp.length] = temp[0..$];
203	}
204
205	size_t _length;
206	T[] _data;
207}