PageRenderTime 60ms CodeModel.GetById 21ms app.highlight 33ms RepoModel.GetById 1ms app.codeStats 0ms

/sparrowhawk/foundation/ESFMap.cpp

http://github.com/jtblatt/duderino
C++ | 826 lines | 530 code | 197 blank | 99 comment | 162 complexity | c67e85e7d1f0926a3c09b843b394c06c MD5 | raw file
  1/** @file ESFMap.cpp
  2 *  @brief A balanced binary tree
  3 *
  4 * Copyright (c) 2009 Yahoo! Inc.
  5 * The copyrights embodied in the content of this file are licensed by Yahoo! Inc.
  6 * under the BSD (revised) open source license.
  7 *
  8 * Derived from code that is Copyright (c) 2009 Joshua Blatt and offered under both
  9 * BSD and Apache 2.0 licenses (http://sourceforge.net/projects/sparrowhawk/).
 10 *
 11 *    $Author: blattj $
 12 *    $Date: 2009/05/25 21:51:08 $
 13 *    $Name:  $
 14 *    $Revision: 1.3 $
 15 */
 16
 17#ifndef ESF_MAP_H
 18#include <ESFMap.h>
 19#endif
 20
 21#ifndef ESF_ASSERT_H
 22#include <ESFAssert.h>
 23#endif
 24
 25#ifdef DEBUG
 26#include <math.h>
 27#endif
 28
 29ESFMapNode::ESFMapNode(ESFMapNode *parent, ESFMapNode *left, ESFMapNode *right,
 30		bool isBlack, const void *key, void *value) :
 31	_parent(parent), _left(left), _right(right), _isBlack(isBlack), _key(key),
 32			_value(value) {
 33}
 34
 35ESFMapNode::~ESFMapNode() {
 36}
 37
 38void *
 39ESFMapNode::operator new(size_t size, ESFAllocator *allocator) {
 40	return allocator->allocate(size);
 41}
 42
 43ESFMap::ESFMap(bool isUnique, ESFComparator *comparator,
 44		ESFAllocator *allocator, ESFLockable *lockable) :
 45	_size(0), _isUnique(isUnique), _root(&_sentinel), _allocator(allocator),
 46			_lockable(lockable), _comparator(comparator),
 47			_sentinel(&_sentinel, &_sentinel, &_sentinel, true, 0, 0)
 48
 49{
 50}
 51
 52ESFMap::~ESFMap() {
 53}
 54
 55ESFError ESFMap::insert(const void *key, void *value) {
 56	if (!key) {
 57		return ESF_NULL_POINTER;
 58	}
 59
 60	if (!_comparator || !_allocator || !_lockable) {
 61		return ESF_INVALID_STATE;
 62	}
 63
 64	if (ESF_UINT32_MAX == _size) {
 65		return ESF_OVERFLOW;
 66	}
 67
 68	ESFMapNode *node = new (_allocator) ESFMapNode(&_sentinel, &_sentinel,
 69			&_sentinel, true, key, value);
 70
 71	if (!node) {
 72		return ESF_OUT_OF_MEMORY;
 73	}
 74
 75	if (false == insertNode(node)) {
 76		node->~ESFMapNode();
 77		_allocator->deallocate((void *) node);
 78
 79		return ESF_UNIQUENESS_VIOLATION;
 80	}
 81
 82	return ESF_SUCCESS;
 83}
 84
 85ESFError ESFMap::erase(const void *key) {
 86	if (!key) {
 87		return ESF_NULL_POINTER;
 88	}
 89
 90	if (!_comparator || !_allocator || !_lockable) {
 91		return ESF_INVALID_STATE;
 92	}
 93
 94	ESFMapNode *node = findNode(_root, key);
 95
 96	if (!node->_key) {
 97		return ESF_CANNOT_FIND;
 98	}
 99
100	deleteNode(node);
101
102	return ESF_SUCCESS;
103}
104
105void *ESFMap::find(const void *key) {
106	if (!key) {
107		return 0;
108	}
109
110	if (!_comparator || !_allocator || !_lockable) {
111		return 0;
112	}
113
114	ESFMapNode *node = findNode(_root, key);
115
116	if (!node->_key) {
117		return 0;
118	}
119
120	return node->_value;
121}
122
123ESFError ESFMap::update(const void *key, void *value, void **old) {
124	if (!key) {
125		return ESF_NULL_POINTER;
126	}
127
128	if (!_comparator || !_allocator || !_lockable) {
129		return ESF_INVALID_STATE;
130	}
131
132	ESFMapNode *node = findNode(_root, key);
133
134	if (!node->_key) {
135		return ESF_CANNOT_FIND;
136	}
137
138	if (old) {
139		*old = node->_value;
140	}
141
142	node->_value = value;
143
144	return ESF_SUCCESS;
145}
146
147ESFError ESFMap::clear() {
148	ESFMapNode *x = _root;
149
150	while (x->_key) {
151		if (x->_right->_key) {
152			x = x->_right;
153
154			continue;
155		}
156
157		if (x->_left->_key) {
158			x = x->_left;
159
160			continue;
161		}
162
163		if (!x->_parent->_key) {
164			ESF_ASSERT(_root == x);
165
166			x->~ESFMapNode();
167			_allocator->deallocate((void *) x);
168
169			_root = &_sentinel;
170
171			_size = 0;
172
173			return ESF_SUCCESS;
174		}
175
176		if (x == x->_parent->_right) {
177			x = x->_parent;
178
179			x->_right->~ESFMapNode();
180			_allocator->deallocate((void *) x->_right);
181
182			x->_right = &_sentinel;
183
184			continue;
185		}
186
187		ESF_ASSERT(x == x->_parent->_left);
188
189		x = x->_parent;
190
191		x->_left->~ESFMapNode();
192		_allocator->deallocate((void *) x->_left);
193
194		x->_left = &_sentinel;
195	}
196
197	return ESF_SUCCESS;
198}
199
200ESFMapIterator ESFMap::getMinimumIterator() {
201	ESFMapIterator iterator(findMinimum(_root));
202
203	return iterator;
204}
205
206ESFMapIterator ESFMap::getMaximumIterator() {
207	ESFMapIterator iterator(findMaximum(_root));
208
209	return iterator;
210}
211
212ESFError ESFMap::insert(const void *key, void *value, ESFMapIterator *iterator) {
213	if (!key || !value || !iterator) {
214		return ESF_NULL_POINTER;
215	}
216
217	if (!_comparator || !_allocator || !_lockable) {
218		return ESF_INVALID_STATE;
219	}
220
221	ESFMapNode *node = new (_allocator) ESFMapNode(&_sentinel, &_sentinel,
222			&_sentinel, true, key, value);
223
224	if (!node) {
225		return ESF_OUT_OF_MEMORY;
226	}
227
228	if (false == insertNode(node)) {
229		node->~ESFMapNode();
230		_allocator->deallocate((void *) node);
231
232		return ESF_UNIQUENESS_VIOLATION;
233	}
234
235	iterator->_node = node;
236
237	return ESF_SUCCESS;
238}
239
240ESFMapIterator ESFMap::findIterator(const void *key) {
241	ESFMapIterator iterator;
242
243	if (!key) {
244		return iterator;
245	}
246
247	if (!_comparator || !_allocator || !_lockable) {
248		return iterator;
249	}
250
251	ESFMapNode *node = findNode(_root, key);
252
253	if (!node) {
254		return iterator;
255	}
256
257	iterator._node = node;
258
259	return iterator;
260}
261
262ESFError ESFMap::erase(ESFMapIterator *iterator) {
263	if (!iterator) {
264		return ESF_NULL_POINTER;
265	}
266
267	if (iterator->isNull()) {
268		return ESF_INVALID_ITERATOR;
269	}
270
271	deleteNode(iterator->_node);
272
273	iterator->_node = 0;
274
275	return ESF_SUCCESS;
276}
277
278ESFError ESFMap::writeAcquire() {
279	if (!_lockable)
280		return ESF_INVALID_STATE;
281
282	return _lockable->writeAcquire();
283}
284
285ESFError ESFMap::readAcquire() {
286	if (!_lockable)
287		return ESF_INVALID_STATE;
288
289	return _lockable->readAcquire();
290}
291
292ESFError ESFMap::writeAttempt() {
293	if (!_lockable)
294		return ESF_INVALID_STATE;
295
296	return _lockable->writeAttempt();
297}
298
299ESFError ESFMap::readAttempt() {
300	if (!_lockable)
301		return ESF_INVALID_STATE;
302
303	return _lockable->readAttempt();
304}
305
306ESFError ESFMap::writeRelease() {
307	if (!_lockable)
308		return ESF_INVALID_STATE;
309
310	return _lockable->writeRelease();
311}
312
313ESFError ESFMap::readRelease() {
314	if (!_lockable)
315		return ESF_INVALID_STATE;
316
317	return _lockable->readRelease();
318}
319
320ESFMapNode *
321ESFMap::findNode(ESFMapNode *x, const void *k) {
322	//
323	//  See Iterative-Tree-Search in "Introduction to Algorithms", Cormen,
324	//  Leiserson, Rivest, p.248.
325	//
326
327	int result = 0;
328
329	while (x->_key) {
330		result = _comparator->compare(k, x->_key);
331
332		if (0 == result) {
333			if (_isUnique) {
334				return x;
335			}
336
337			//
338			//  This is a departure from Cormen et. al.'s algorithm.  If the
339			//  map allows multiple elements with the same key, we could have
340			//  inserted them to the right of the current node.  We always
341			//  return the node that is the "smallest" one in the tree so that
342			//  any iteration from this point would yield a different key
343			//  if it did a getPrevious() and could yield a node with the
344			//  same key if it did a getNext().
345			//
346			ESFMapNode *y = 0;
347
348			while (true) {
349				y = findSuccessor(x);
350
351				if (!y->_key)
352					break;
353
354				if (0 != _comparator->compare(y->_key, x->_key))
355					break;
356
357				x = y;
358			}
359
360			return x;
361		} else if (0 < result) {
362			x = x->_right;
363		} else {
364			x = x->_left;
365		}
366	}
367
368	return &_sentinel;
369}
370
371ESFMapNode *
372ESFMap::findMinimum(ESFMapNode *x) {
373	//
374	//  See Tree-Minimum in "Introduction to Algorithms", Cormen, Leiserson,
375	//  Rivest, p. 248.
376	//
377
378	while (x->_left->_key) {
379		x = x->_left;
380	}
381
382	return x;
383}
384
385ESFMapNode *
386ESFMap::findMaximum(ESFMapNode *x) {
387	//
388	//  See Tree-Maximum in "Introduction to Algorithms", Cormen, Leiserson,
389	//  Rivest, p. 248.
390	//
391
392	while (x->_right->_key) {
393		x = x->_right;
394	}
395
396	return x;
397}
398
399ESFMapNode *
400ESFMap::findSuccessor(ESFMapNode *x) {
401	//
402	//  See Tree-Successor in "Introduction to Algorithms", Cormen, Leiserson,
403	//  Rivest, p. 249.
404	//
405
406	if (x->_right->_key) {
407		return findMinimum(x->_right);
408	}
409
410	ESFMapNode *y = x->_parent;
411
412	while (y->_key && x == y->_right) {
413		x = y;
414		y = y->_parent;
415	}
416
417	return y;
418}
419
420ESFMapNode *
421ESFMap::findPredecessor(ESFMapNode *x) {
422	//
423	//  See Tree-Successor in "Introduction to Algorithms", Cormen, Leiserson,
424	//  Rivest, p. 249.
425	//
426	//  Tree-Predecessor is symmetric to Tree-Successor.
427	//
428
429	if (x->_left->_key) {
430		return findMaximum(x->_left);
431	}
432
433	ESFMapNode *y = x->_parent;
434
435	while (y->_key && x == y->_left) {
436		x = y;
437		y = y->_parent;
438	}
439
440	return y;
441}
442
443bool ESFMap::insertNode(ESFMapNode *z) {
444	//
445	//  See Tree-Insert in "Introduction to Algorithms", Cormen, Leiserson,
446	//  Rivest, p. 251.
447	//
448
449	int result = 0;
450	ESFMapNode *y = &_sentinel;
451	ESFMapNode *x = _root;
452
453	while (x->_key) {
454		y = x;
455
456		result = _comparator->compare(z->_key, x->_key);
457
458		if (0 > result) {
459			x = x->_left;
460		} else if (0 < result) {
461			x = x->_right;
462		} else if (_isUnique) {
463			return false;
464		} else {
465			break;
466		}
467	}
468
469	z->_parent = y;
470	z->_left = &_sentinel;
471	z->_right = &_sentinel;
472
473	if (&_sentinel == y) {
474		_root = z;
475	} else if (0 > result) {
476		y->_left = z;
477	} else {
478		y->_right = z;
479	}
480
481	++_size;
482
483	//
484	//  See RB-Insert in "Introduction to Algorithms", Cormen, Leiserson,
485	//  Rivest, p. 268.
486	//
487
488	x = z;
489
490	x->_isBlack = false;
491
492	while (x != _root && false == x->_parent->_isBlack) {
493		if (x->_parent == x->_parent->_parent->_left) {
494			y = x->_parent->_parent->_right;
495
496			if (false == y->_isBlack) {
497				x->_parent->_isBlack = true;
498				y->_isBlack = true;
499				x->_parent->_parent->_isBlack = false;
500				x = x->_parent->_parent;
501			} else if (x == x->_parent->_right) {
502				x = x->_parent;
503				leftRotate(x);
504			} else {
505				x->_parent->_isBlack = true;
506				x->_parent->_parent->_isBlack = false;
507				rightRotate(x->_parent->_parent);
508			}
509		} else {
510			y = x->_parent->_parent->_left;
511
512			if (false == y->_isBlack) {
513				x->_parent->_isBlack = true;
514				y->_isBlack = true;
515				x->_parent->_parent->_isBlack = false;
516				x = x->_parent->_parent;
517			} else if (x == x->_parent->_left) {
518				x = x->_parent;
519				rightRotate(x);
520			} else {
521				x->_parent->_isBlack = true;
522				x->_parent->_parent->_isBlack = false;
523				leftRotate(x->_parent->_parent);
524			}
525		}
526	}
527
528	_root->_isBlack = true;
529
530	return true;
531}
532
533void ESFMap::deleteNode(ESFMapNode *z) {
534	//
535	//  See RB-Delete in "Introduction to Algorithms", Cormen, Leiserson,
536	//  Rivest, p. 273.
537	//
538
539	ESFMapNode *y = 0;
540	ESFMapNode *x = 0;
541
542	if (!z->_left->_key || !z->_right->_key) {
543		y = z;
544	} else {
545		y = findSuccessor(z);
546	}
547
548	if (y->_left->_key) {
549		x = y->_left;
550	} else {
551		x = y->_right;
552	}
553
554	x->_parent = y->_parent;
555
556	if (!y->_parent->_key) {
557		_root = x;
558	} else if (y == y->_parent->_left) {
559		y->_parent->_left = x;
560	} else {
561		y->_parent->_right = x;
562	}
563
564	bool isBlack = y->_isBlack;
565
566	if (y != z) {
567		//
568		//  Cormen et. al. simplify this step by copying all fields from
569		//  y into z, but since this would violate our iterator invalidation
570		//  rules, we really have to replace node z with node y.
571		//
572
573		//  Replace all of y's links with z's
574
575		y->_parent = z->_parent;
576		y->_left = z->_left;
577		y->_right = z->_right;
578		y->_isBlack = z->_isBlack;
579
580		//  Change the all the links that point to z to instead point to y.
581
582		y->_right->_parent = y;
583		y->_left->_parent = y;
584
585		if (z == y->_parent->_right) {
586			y->_parent->_right = y;
587		} else {
588			y->_parent->_left = y;
589		}
590
591		//  If z was the root, y is now the root.
592
593		if (_root == z) {
594			_root = y;
595		}
596	}
597
598	z->~ESFMapNode();
599	_allocator->deallocate((void *) z);
600	z = 0;
601
602	--_size;
603
604	if (!isBlack)
605		return;
606
607	//
608	//  See RB-Delete-Fixup in "Introduction to Algorithms", Cormen, Leiserson,
609	//  Rivest, p. 274.
610	//
611
612	ESFMapNode *w = 0;
613
614	while (_root != x && x->_isBlack) {
615		if (x == x->_parent->_left) {
616			w = x->_parent->_right;
617
618			if (!w->_isBlack) {
619				w->_isBlack = true;
620				x->_parent->_isBlack = false;
621				leftRotate(x->_parent);
622				w = x->_parent->_right;
623			}
624
625			if (w->_left->_isBlack && w->_right->_isBlack) {
626				w->_isBlack = false;
627				x = x->_parent;
628			} else if (w->_right->_isBlack) {
629				w->_left->_isBlack = true;
630				w->_isBlack = false;
631				rightRotate(w);
632				w = x->_parent->_right;
633			} else {
634				w->_isBlack = x->_parent->_isBlack;
635				x->_parent->_isBlack = true;
636				w->_right->_isBlack = true;
637				leftRotate(x->_parent);
638				x = _root;
639			}
640		} else {
641			w = x->_parent->_left;
642
643			if (!w->_isBlack) {
644				w->_isBlack = true;
645				x->_parent->_isBlack = false;
646				rightRotate(x->_parent);
647				w = x->_parent->_left;
648			}
649
650			if (w->_right->_isBlack && w->_left->_isBlack) {
651				w->_isBlack = false;
652				x = x->_parent;
653			} else if (w->_left->_isBlack) {
654				w->_right->_isBlack = true;
655				w->_isBlack = false;
656				leftRotate(w);
657				w = x->_parent->_left;
658			} else {
659				w->_isBlack = x->_parent->_isBlack;
660				x->_parent->_isBlack = true;
661				w->_left->_isBlack = true;
662				rightRotate(x->_parent);
663				x = _root;
664			}
665		}
666	}
667
668	x->_isBlack = true;
669}
670
671void ESFMap::rightRotate(ESFMapNode *x) {
672	//
673	//  See Left-Rotate in "Introduction to Algorithms", Cormen, Leiserson,
674	//  Rivest, p. 266.
675	//
676	//  Right-Rotate is symmetric to Left-Rotate.
677	//
678
679	ESFMapNode *y = x->_left;
680
681	x->_left = y->_right;
682
683	if (y->_right->_key) {
684		y->_right->_parent = x;
685	}
686
687	y->_parent = x->_parent;
688
689	if (!x->_parent->_key) {
690		_root = y;
691	} else if (x == x->_parent->_right) {
692		x->_parent->_right = y;
693	} else {
694		x->_parent->_left = y;
695	}
696
697	y->_right = x;
698	x->_parent = y;
699}
700
701void ESFMap::leftRotate(ESFMapNode *x) {
702	//
703	//  See Left-Rotate in "Introduction to Algorithms", Cormen, Leiserson,
704	//  Rivest, p. 266.
705	//
706
707	ESFMapNode *y = x->_right;
708
709	x->_right = y->_left;
710
711	if (y->_left->_key) {
712		y->_left->_parent = x;
713	}
714
715	y->_parent = x->_parent;
716
717	if (!x->_parent->_key) {
718		_root = y;
719	} else if (x == x->_parent->_left) {
720		x->_parent->_left = y;
721	} else {
722		x->_parent->_right = y;
723	}
724
725	y->_left = x;
726	x->_parent = y;
727}
728
729ESFUInt32 ESFMap::getSize() const {
730	return _size;
731}
732
733bool ESFMap::isEmpty() const {
734	return 0 == _size;
735}
736
737#ifdef DEBUG
738bool ESFMap::isBalanced() const {
739	int height = 0;
740	int blackHeight = 0;
741	bool unbalanced = false;
742
743	height = getHeight(_root);
744
745	//
746	//  See Lemma 14.1 in "Introduction to Algorithms", Cormen, Leiserson,
747	//  Rivest, p. 264.
748	//
749	//  "A red-black tree with n internal nodes has a height at most 2lg(n+1).
750	//
751
752	if (height > 2 * (log10(_size + 1) / log10(2))) {
753		return false;
754	}
755
756	//
757	//  See red-black properties in "Introduction to Algorithms", Cormen,
758	//  Leiserson, Rivest, p. 263.
759	//
760	//  "Every simple path from a node to a descendant leaf contains the
761	//  same number of black nodes."
762	//
763
764	blackHeight = getBlackHeight(_root, &unbalanced);
765
766	return !unbalanced;
767}
768
769int ESFMap::getBlackHeight(ESFMapNode *node, bool *unbalanced) const {
770	//
771	//  Base case.
772	//
773	if (!node->_key) {
774		ESF_ASSERT( node->_isBlack );
775		return 0;
776	}
777
778	int right = getBlackHeight(node->_right, unbalanced);
779	int left = getBlackHeight(node->_left, unbalanced);
780
781	if (right != left) {
782		*unbalanced = true;
783	}
784
785	if (node->_isBlack) {
786		return (right > left) ? right + 1 : left + 1;
787	}
788
789	return (right > left) ? right : left;
790}
791
792int ESFMap::getHeight(ESFMapNode *node) const {
793	//
794	//  Base case.
795	//
796	if (!node->_key) {
797		return 0;
798	}
799
800	int right = getHeight(node->_right);
801	int left = getHeight(node->_left);
802
803	return (right > left) ? right + 1 : left + 1;
804}
805
806#endif  /* defined DEBUG */
807
808ESFSize ESFMap::GetAllocationSize() {
809	return sizeof(ESFMapNode);
810}
811
812ESFMapIterator::ESFMapIterator() :
813	_node(0) {
814}
815
816ESFMapIterator::ESFMapIterator(ESFMapNode *node) :
817	_node(node) {
818}
819
820ESFMapIterator::ESFMapIterator(const ESFMapIterator &iterator) :
821	_node(iterator._node) {
822}
823
824ESFMapIterator::~ESFMapIterator() {
825}
826