// rbt.h Dictionary class implementated by red-black tree method. // based on Sedgwick, Algorithms in C++, chapter 15 -saunders 2/96 // templatized 3/00, -bds #ifndef rbt_ #define rbt_ #include #define debug(s, v) //#define debug(s, v) (cerr << (s) << (v) << '\n') /***************************************************************** This red-black tree implementation is parameterized by a keyType and an infoType. The keyType must be a totally ordered type including a minimum value, keyMIN, which will not occur in user data. I/O to streams must be supported. Operators required: keyType < keyType, cout << keyType, cin >> keyType keyMIN < key must be true for all keys used. The infoType must be an equality testable type including a special value, infoNIL, indicating no info. I/O to streams must be supported. Operators required: infoType == infoType, infoType != infoType, cout << infoType, cin >> infoType infoNIL != info must be true for all info used. *****************************************************************/ template class Dict {public: Dict(int max = 0); ~Dict(){} /////////////////////////// //// The fundamental Dictionary functions are search and insert // search returns the info associated with key v in the dictionary. // It returns infoNIL if there is no associated info. infoType search(keyType v); // insert puts info in the dictionary associated with the key v. void insert (keyType v, infoType info); /////////////////////////// //// Aux functions display() and black_depth() are also provided. // display makes an ascii display of the red-black tree. void display (int flag); // black_depth returns the current depth of the tree counting // only black edges. int black_depth(); private: struct node /* your basic binary tree node + color bit */ { keyType key; infoType info; bool red_up; /* this being true means edge from parent is red */ node* L; node* R; /* left and right child links */ node(keyType k, infoType i, bool color, node* lefty, node* righty) {key = k; info = i; red_up = color; L = lefty; R = righty; } }; node* head; node* z; node* x; node* p; /* variables used by insert() */ node* g; node* gg; /* and its pawn split() */ void split(/* node* x, node* p, node* g, node* gg*/) { splits++; x->red_up = true; x->L->red_up = false; x->R->red_up = false; if (p->red_up) { g->red_up = true; if ((p == g->L) != (x == p->L)) p = rotate(x, p, g); x = rotate(p, g, gg); x->red_up = false; } } node* rotate(node* gc, node* c, node* y) { rotations++; if (c->L == gc) { c->L = gc->R; gc->R = c;} else { c->R = gc->L; gc->L = c;} if (y->L == c) y->L = gc; else y->R = gc; return gc; } int splits; int rotations; /* counters used for analysis only */ void display_tree(node * T, int offset) /* used by display */ { const int shift = 4; if (T != z) { if (T->red_up) { display_tree(T->R, offset); for (int i = 0; i < offset-shift+1; i++) cout << " "; cout << T->key << '\n'; display_tree(T->L, offset); } else { display_tree(T->R, offset+shift); for (int i = 0; i < offset; i++) cout << " "; cout << T->key << '\n'; display_tree(T->L, offset+shift); } } else { /* for (int i = 0; i < offset; i++) cout << " "; cout << ".\n"; */ } } }; template Dict::Dict(int max = 0) { z = new node(keyMIN, infoNIL, false, 0, 0); z->L = z->R = z; head = new node (keyMIN, infoNIL, false, 0, z); splits = 0; rotations = 0; } template infoType Dict::search(keyType v) { node* x = head->R; z->key = v; while (v < x->key || v > x->key) x = (v < x->key) ? x->L : x->R; return x->info; } template void Dict::insert (keyType v, infoType info) { x = head; p = head; g = head; while (x != z) { gg = g; g = p; p = x; x = (v < x->key) ? x->L : x->R; if (x->L->red_up && x->R->red_up) split(); } x = new node(v, info, true, z, z); if (v < p->key) p->L = x; else p->R = x; if (p->red_up) split(); /* in case rotations needed at the new node */ head->R->red_up = false; /* in case we've had a split at the root */ } template void Dict::display (int flag) { if (flag) { cout << "0 1 2 3 4 5 6 7 8 9 10 <-- depths\n"; display_tree(head->R, 0); } cout << "There have been " << splits <<" splits and " << rotations << " rotations.\n"; } template int Dict::black_depth() { int d = 0; for (node* x = head->R; x != z; x = x->L) if (!(x->red_up)) d++; return d; } #endif