⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 d_rbtree.h

📁 这是数据结构和算法的国外经典书籍.清华大学出版社出版的<数据结构C++语言描述-应用模板库STL>陈君 译 英文名称是Data Structures with C++ Using STL.
💻 H
📖 第 1 页 / 共 2 页
字号:
#ifndef RED_BLACK_TREE_CLASS
#define RED_BLACK_TREE_CLASS

#ifdef _MSC_VER
// disable warning messages that identifier was truncated
// to 'number' characters in the debug information
#pragma warning(disable:4786)
#endif	// _MSC_VER

#include <iostream>
#include <iomanip>
#include <queue>
#include <string>
#include <utility>
#include <strstream>

#include "d_except.h"

using namespace std;

enum colorType {RED, BLACK};

// each node of a red-black tree is of type rbnode
template <typename T>
class rbnode
{
	public:
		colorType color;		// node's color
		rbnode<T> *parent;	// node's parent
		rbnode<T> *left;		// node's left child
		rbnode<T> *right;		// node's right child
		T nodeValue;

		// constructors
		rbnode(const T& item, rbnode<T> *leftPtr, rbnode<T> *rightPtr,
			    rbnode<T> *parentPtr, colorType c):
					nodeValue(item), left(leftPtr),
					right(rightPtr), parent(parentPtr),color(c)
		{}

		rbnode()
		{}
};

// objects hold a formatted label string and the level,column
// coordinates for a shadow tree node
class rbnodeShadow
{
	public:
		string nodeValueStr;	// formatted node value
		int level,column;
		rbnodeShadow *left, *right;

		rbnodeShadow ()
		{}
};

template <typename T>
class rbtree
{
	public:

#include "d_rbiter.h"
		// iterator nested classes

		rbtree();
			// constructor. create an empty tree

		rbtree(T *first, T *last);
			// constructor. initialize the tree with the data in the
			// range [first, last)

		rbtree(const rbtree<T>& obj);
			// copy constructor

		~rbtree();
			// destructor. erase the tree

		rbtree<T>& operator= (const rbtree<T>& rhs);
			// overloaded assignment

		bool empty() const;
			// is the tree empty?

		int size() const;
			// return the number of values in the tree

		iterator find(const T& item);
			// search for item. if found, return an iterator pointing
			// at it in the tree; otherwise, return end()
		const_iterator find(const T& item) const;
			// constant version

		pair<iterator, bool> insert(const T& item);
			// if item is not in the tree, insert it and
			// return a pair whose iterator component points
			// at item and whose bool component is true. if item
			// is in the tree, return a pair whose iterator
			// component points at the existing item and whose
			// bool component is false
			// Postcondition: the tree size increases by 1 if item
			// is not in the tree

		int erase(const T& item);
			// if item is in the tree, erase it and return 1;
			// otherwise, return 0
			// Postcondition: the tree size decreases by 1 if
			// item is in the tree

		void erase(iterator pos);
			// erase the item pointed to by pos.
			// Precondition: the tree is not empty and pos points
			// to an item in the tree. if the iterator is invalid, the
			// function throws the referenceError exception.
			// Postcondition: the tree size decreases by 1

		void erase(iterator first, iterator last);
			// erase all items in the range [first, last).
			// Precondition: the tree is not empty. if the tree
			// is empty, the function throws the underflowError
			// exception.
			// Postcondition: the size of the tree decreases by
			// the number of elements in the range [first, last)

		iterator begin();
			// return an iterator pointing to the first item
			// inorder
		const_iterator begin() const;
			// constant version
		iterator end();
			// return an iterator pointing just past the end of
			// the tree data
		const_iterator end() const;
			// constant version

		void displayTree(int maxCharacters) const;
			// tree display function. maxCharacters is the
			// largest number of characters required to draw
			// the value of a node

	private:

		int treeSize;		// number of nodes in the tree
		rbnode<T> *root;	// root of the tree

		static rbnode<T> *NIL;
			// used instead of NULL to represent an empty subtree. NIL
			// is shared by all rbtree<T> objects. its pointers are NULL,
			// and its color is BLACK. it participates in rotations,
			// just like any other node

		void makeEmptyTree();
			// create an empty tree. used by two constructors

		rbnode<T> *copyTree(rbnode<T> *t);
			// create a tree that is a copy of t, and return its root pointer

		void deleteTree(rbnode<T> *t);
			// erase the tree with root t

		rbnode<T> *getRBNode(const T& item, rbnode<T> *leftPtr, rbnode<T> *rightPtr,
									rbnode<T> *parentPtr, colorType c);
			// allocate a new tree node and return a pointer to it.
			// if memory allocation fails, the function throws the
			// memoryAllocationError exception

		rbnode<T> *findNode(const T& item) const;
			// search for item in the tree. if it is in the tree,
			// return a pointer to its node; otherwise, return NIL.
			// used by find() and erase()

		void split4Node(rbnode<T> *x);
			// break up a 4-node, performing a rotation, if necessary

		void rotateRight (rbnode<T> *pivot);
			// perform a single right rotation

		void rotateLeft (rbnode<T> *pivot);
			// perform a single left rotation

		void rbDeleteFixup(rbnode<T> *x);
			// fix up the tree when x is the child of
			// a BLACK node that was unlinked from its
			// position in the tree

		rbnodeShadow *buildShadowTree(rbnode<T> *t, int level, int& column) const;
			// recursive function that builds a subtree of the shadow tree
			// corresponding to node t of the tree we are drawing. level is the
			// level-coordinate for the root of the subtree, and column is the
			// changing column-coordinate of the tree nodes

		void deleteShadowTree(rbnodeShadow *t) const;
			// remove the shadow tree from memory after displayTree()
			// displays the red-black tree
};

// declare NIL
template <typename T>
rbnode<T> *rbtree<T>::NIL = 0;

template <typename T>
void rbtree<T>::makeEmptyTree()
{
	if (NIL == 0)
	{
		// first time an rbtree object created. initialize
		// NIL. all its pointers are NULL, and its color
		// is BLACK

		NIL = new rbnode<T>;

		NIL->right = NULL;
		NIL->left = NULL;
		NIL->parent = NULL;
		NIL->color = BLACK;
	}

	// root is NIL, tree size is 0
	root = NIL;
	treeSize = 0;
}

template <typename T>
rbnode<T> *rbtree<T>::copyTree(rbnode<T> *t)
{
	rbnode<T> *newLeft, *newRight, *newNode;

	// if tree branch NIL, return NIL
	if (t == NIL)
		return NIL;

	// copy the left branch of root t and assign its root to newLptr
	newLeft = copyTree(t->left);

	// copy the right branch of tree t and assign its root to newRptr
	newRight = copyTree(t->right);

	// allocate storage for the current root node and assign its
	// data, left and right pointers pointers and color. if newNode
	// is root, NIL is the correct value for its parent pointer
	newNode = getRBNode(t->nodeValue, newLeft, newRight, NIL, t->color);

	// the parent of each non-NIL child is newNode
	if (newLeft != NIL)
		newLeft->parent = newNode;

	if (newRight != NIL)
		newRight->parent = newNode;

	return newNode;
}

template <typename T>
void rbtree<T>::deleteTree(rbnode<T> *t)
{
	 // if current root node is not NIL, erase its left subtree,
	 // its right subtree and then the node itself
	 if (t != NIL)
	 {
		  deleteTree(t->left);
		  deleteTree(t->right);
		  delete t;
	 }
}

template <typename T>
rbnode<T> *rbtree<T>::getRBNode(const T& item, rbnode<T> *leftPtr, rbnode<T> *rightPtr,
		 rbnode<T> *parentPtr, colorType c)
{
	rbnode<T> *newNode;

	newNode = new rbnode<T>(item, leftPtr, rightPtr, parentPtr, c);
	if (newNode == NULL)
		throw memoryAllocationError("rbtree: memory allocation failure");

	return newNode;
}

// search for data item in the tree. if found, return its node
// address; otherwise, return NIL
template <typename T>
rbnode<T> *rbtree<T>::findNode(const T& item) const
{
	// cycle t through the tree starting with root
	rbnode<T> *t = root;

	// terminate on on empty subtree
	while(t != NIL && !(item == t->nodeValue))
		if (item < t->nodeValue)
			t = t->left;
		else
			t = t->right;

	// return pointer to node; NIL if not found
	return t;
}

template <typename T>
void rbtree<T>::split4Node(rbnode<T> *x)
{
	// perform the color flip
	x->color = RED;
	x->left->color = BLACK;
	x->right->color = BLACK;

	// if we split the root, we are done
	if (x == root)
		return;

	// to see if a rotation is required, we need the
	// parent of x. x is not root, so p != NIL
	rbnode<T> *p = x->parent;

	// a rotation is needed if the parent of x is RED
	if (p->color == RED)
	{
		// we need the grandparent of x. since the root
		// is BLACK, p cannot be root, so the grandparent
		// exists
		rbnode<T> *g = x->parent->parent;

		// the grandparent of x will be RED
		g->color = RED;

		// a double rotation is required if x is an inside
		// grandchild. check this by seeing if the orientations
		// of p to g and x to p are different
		if ( p == g->left && x == p->right )
		{
			// perform a double right rotation
			// first move x up one level and p down
			rotateLeft(x);

			// node x will be BLACK
			x->color = BLACK;
			// prepare for a right single rotation
			p = x;
		}
		else if ( p == g->right && x == p->left )
		{
			// perform a double left rotation
			// first move x up one level and p down
			rotateRight(x);

			// node x will be BLACK
			x->color = BLACK;
			// prepare for a left single rotation
			p = x;
		}
		else
			// single rotation. parent will be BLACK
			p->color = BLACK;

		// perform a single rotation
		// move p up and g down
		if (p == g->left)
			rotateRight(p);
		else
			rotateLeft(p);
	}
}

template <typename T>
void rbtree<T>::rotateRight (rbnode<T> *pivot)
{
	// need the parent and grandparent of pivot
	rbnode<T> *p = pivot->parent, *g = pivot->parent->parent;

	// adjust right and left pointers
	p->left = pivot->right;
	pivot->right = p;

	// adjust parent pointers
	pivot->parent = g;
	p->parent = pivot;
	// don't reset the parent link of the left child of p
	// if the left child is NIL. this will interfere with
	// the use of NIL in rbDeleteFixup()
	if (p->left != NIL)
		p->left->parent = p;

	if (p == root)
		// pivot is the new root
		root = pivot;
	else if (p == g->right)
		// right link of g must point at pivot now
		g->right = pivot;
	else
		// left link of g must point at pivot now
		g->left = pivot;
}

// code is the same as the single right rotation,
// with left and right interchanged
template <typename T>
void rbtree<T>::rotateLeft (rbnode<T> *pivot)
{
	rbnode<T> *p = pivot->parent, *g = pivot->parent->parent;

	p->right = pivot->left;
	pivot->left = p;

	pivot->parent = g;
	p->parent = pivot;
	if (p->right != NIL)
		p->right->parent = p;

	if (p == root)
	  root = pivot;
	else if (p == g->right)
		g->right = pivot;
	else
		g->left = pivot;
}

template <typename T>
void rbtree<T>::rbDeleteFixup(rbnode<T> *x)
{
	rbnode<T> *siblingOfx;

	while (x != root && x->color == BLACK)

		if (x == x->parent->left)
		{
			siblingOfx = x->parent->right;

			if (siblingOfx->color == RED)
			{
				// CASE 1:
				//    sibling of x is RED. perform
				//    color changes and a left rotation.
				//    this produces a configuration that
				//    corresponds to cases 2, 3, or 4
				siblingOfx->color = BLACK;
				x->parent->color = RED;
				rotateLeft(siblingOfx);
				siblingOfx = x->parent->right;
			}

			if (siblingOfx->left->color == BLACK &&
				 siblingOfx->right->color == BLACK)
			{
				// CASE 2:
				//    both the children of the siblingOfx are BLACK.
				//    take a BLACK off of x and siblingOfx. x now
				//    has only one BLACK, and siblingOfx is RED.
				//    consider parent(x) to have an extra BLACK.
				//    if we enter this case after executing case 1,
				//    x becomes RED, and the loop terminates
				siblingOfx->color = RED;
				x = x->parent;
			}
			else
			{
				if (siblingOfx->right->color == BLACK)
				{
					// CASE 3:
					//    siblingOfx is BLACK, its left child is
					//    RED, and its right child is BLACK. perform
					//    color changes and right rotation. this
					//    transforms the node configuration into
					//    case 4, which termintes the loop

					siblingOfx->left->color = BLACK;
					siblingOfx->color = RED;
					rotateRight(siblingOfx->left);
					siblingOfx = x->parent->right;
				}

				// CASE 4:
				//    siblingOfx is BLACK and siblingOfx has a
				//    RED right child. after color changes
				//    and a left rotation, the extra BLACK on
				//    x is removed. set x to the root to terminate
				//    the loop
				siblingOfx->color = x->parent->color;
				x->parent->color = BLACK;
				siblingOfx->right->color = BLACK;
				rotateLeft(siblingOfx);
				x = root;
			}
		}
		else	// same as x == x->parent->left, except that
				// "left" and "right" are interchanged
		{
			siblingOfx = x->parent->left;

			if (siblingOfx->color == RED)
			{
				siblingOfx->color = BLACK;
				x->parent->color = RED;
				rotateRight(siblingOfx);
				siblingOfx = x->parent->left;
			}

			if (siblingOfx->right->color == BLACK &&
				 siblingOfx->left->color == BLACK)
			{
				siblingOfx->color = RED;
				x = x->parent;
			}
			else
			{
				if (siblingOfx->left->color == BLACK)
				{
					siblingOfx->right->color = BLACK;
					siblingOfx->color = RED;
					rotateLeft(siblingOfx->right);
					siblingOfx = x->parent->left;
				}

				siblingOfx->color = x->parent->color;
				x->parent->color = BLACK;
				siblingOfx->left->color = BLACK;
				rotateRight(siblingOfx);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -