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

📄 avl.h

📁 常用算法与数据结构原代码
💻 H
字号:
// AVL tree
#ifndef AVLtree_
#define AVLtree_

#include "avlnode.h"
#include "stack.h"
#include "xcept.h"

template<class E, class K>
class AVLtree 
{
public:
	AVLtree() 
	{
		root = 0;
	}
	~AVLtree() 
	{
		Erase(root);
	}
	bool Search(const K& k, E& e) const;
	AVLtree<E,K>& Insert(const E& e);
	AVLtree<E,K>& Delete(const K& k, E& e);
	void Ascend() 
	{
		InOutput(root);
		cout << endl;
	}
	void PostOut() 
	{
		PostOutput(root);
		cout << endl;
	}
protected:
	AVLNode<E,K> *root;  // root node
	void Erase(AVLNode<E,K> *t);
	void InOutput(AVLNode<E,K> *t);
	void PostOutput(AVLNode<E,K> *t);
	void FixBF(AVLNode<E,K> *, AVLNode<E,K>*, const E&);
	void RRrotate(AVLNode<E,K> *, AVLNode<E,K>*, AVLNode<E,K> *);
	void LLrotate(AVLNode<E,K> *, AVLNode<E,K>*, AVLNode<E,K> *);
	void RLrotate(AVLNode<E,K> *, AVLNode<E,K>*, AVLNode<E,K> *);
	void LRrotate(AVLNode<E,K> *, AVLNode<E,K>*, AVLNode<E,K> *);
};

template<class E, class K>
void AVLtree<E,K>::Erase(AVLNode<E,K> *t)
{// Delete all nodes in AVL tree with root t.
	// Use a postorder traversal.
	if (t) 
	{
		Erase(t->LeftChild);
		Erase(t->RightChild);
		delete t;
	}
}

template<class E, class K>
bool AVLtree<E,K>::Search(const K& k, E &e) const
{// Search for element that matches k.
	
	// pointer p starts at the root and moves through
	// the tree looking for an element with key k
	AVLNode<E,K> *p = root;
	while (p) // examine p->data
	{
		if (k < p->data) 
			p = p->LeftChild;
		else if (k > p->data) 
			p = p->RightChild;
		else 
		{// found element
			e = p->data;
			return true;
		}
	}
	return false;
}

template<class E, class K>
void AVLtree<E,K>::FixBF(AVLNode<E,K> *q, AVLNode<E,K> *r, const E &e)
{// Balance factors from q to r were originally 0.
	// They need to be changed to +1 or -1.
	// Use e to find path from q to r.
	
	while (q != r)
	{
		if (e < q->data) 
		{
			// height of left subtree has increased
			q->bf = 1;
			q = q->LeftChild;
		}
		else
		{
			// height of right subtree has increased
			q->bf = -1;
			q = q->RightChild;
		}
	}
}

template<class E, class K>
void AVLtree<E,K>::LLrotate(AVLNode<E,K> *PA, AVLNode<E,K> *A, AVLNode<E,K> *B)
{// LL rotation around A.  PA is parent of A
	// and B left child of A.
	
	// restructure subtree at A
	A->LeftChild = B->RightChild;
	B->RightChild = A;
	if (PA) // A is not the root
	{
		if (A == PA->LeftChild)
			PA->LeftChild = B;
		else 
			PA->RightChild = B;
	}
	else 
		root = B;
	
	// set balance factors
	A->bf = B->bf = 0;
}

template<class E, class K>
void AVLtree<E,K>::RRrotate(AVLNode<E,K> *PA, AVLNode<E,K> *A, AVLNode<E,K> *B)
{// RR rotation around A.  PA is parent of A
	// and B right child of A.
	
	// restructure subtree at A
	A->RightChild = B->LeftChild;
	B->LeftChild = A;
	if (PA) // A is not the root
	{
		if (A == PA->LeftChild)
			PA->LeftChild = B;
		else 
			PA->RightChild = B;
	}
	else 
		root = B;
	
	// set balance factors
	A->bf = B->bf = 0;
}

template<class E, class K>
void AVLtree<E,K>::LRrotate(AVLNode<E,K> *PA, AVLNode<E,K> *A, AVLNode<E,K> *B)
{// LR rotation around A.  PA is parent of A
	// and B left child of A.
	
	AVLNode<E,K> *C = B->RightChild;
	
	// restructure subtree at A
	A->LeftChild = C->RightChild;
	B->RightChild = C->LeftChild;
	C->LeftChild = B;
	C->RightChild = A;
	if (PA) // A is not the root
	{
		if (A == PA->LeftChild)
			PA->LeftChild = C;
		else 
			PA->RightChild = C;
	}
	else
		root = C;
	
	// set balance factors
	int b = C->bf;
	if (b == 1) 
	{
		B->bf = 0;
		A->bf = -1;
	}
	else if (b) 
	{
		B->bf = 1;
		A->bf = 0;
	}
    else // b = 0
		B->bf = A->bf = 0;
	
	C->bf = 0;
}

template<class E, class K>
void AVLtree<E,K>::RLrotate(AVLNode<E,K> *PA, AVLNode<E,K> *A, AVLNode<E,K> *B)
{// RL rotation around A.  PA is parent of A
	// and B left child of A.
	
	AVLNode<E,K> *C = B->LeftChild;
	
	// restructure subtree at A
	A->RightChild = C->LeftChild;
	B->LeftChild = C->RightChild;
	C->LeftChild = A;
	C->RightChild = B;
	if (PA) // A is not the root
	{
		if (A == PA->LeftChild)
			PA->LeftChild = C;
		else 
			PA->RightChild = C;
	}
	else 
		root = C;
	
	// set balance factors
	int b = C->bf;
	if (b == 1) 
	{
		B->bf = -1;
		A->bf = 0;
	}
	else if (b) 
	{
		B->bf = 0;
		A->bf = 1;
	}
    else // b = 0
		B->bf = A->bf = 0;
	
	C->bf = 0;
}

template<class E, class K>
AVLtree<E,K>& AVLtree<E,K>::Insert(const E& e)
{// Insert e if not duplicate.
	AVLNode<E,K> *p = root,  // search pointer
		*pp = 0,    // parent of p
		*A = 0,     // node with bf != 0
		*PA;        // parent of A
	// find place to insert
	// also record most recent node with bf != 0
	// in A and its parent in PA
	while (p)
	{// examine p->data
		if (p->bf) 
		{// new candidate for A node
			A = p;
			PA = pp;
		}
		pp = p;
		// move p to a child
		if (e < p->data) 
			p = p->LeftChild;
		else if (e > p->data) 
			p = p->RightChild;
		else 
			throw BadInput(); // duplicate
	}
	
	// get a node for e and attach to pp
	AVLNode<E,K> *r = new AVLNode<E,K> (e);
	if (root) 
	{// tree not empty
		if (e < pp->data) 
			pp->LeftChild = r;
		else 
			pp->RightChild = r;
	}
	else 
	{// insertion into empty tree
		root = r;
		return *this;
	}
	
	// see if we must rebalance or simply change
	// balance factors
	if (A) // possible rebalancing needed
	{
		if (A->bf < 0) // bf = -1 before insertion
		{
			if (e < A->data) 
			{// insertion in left subtree
                // height of left subtree has increased by 1
                // new bf of A is 0, no rebalancing
                A->bf = 0;
                // fix bf on path from A to r
                FixBF(A->LeftChild,r,e);
			}
			else 
			{// insertion in right subtree
                // bf of A is -2, rebalance
                AVLNode<E,K> *B = A->RightChild;
                if (e > B->data) 
				{// RR case
					FixBF(B->RightChild,r,e);
					RRrotate(PA,A,B);
				}
                else 
				{// RL case
					FixBF(B->LeftChild,r,e);
					RLrotate(PA,A,B);
				}
			}
		}
		else // bf = +1 before insertion
		{
			if (e > A->data) 
			{// insertion in right subtree
				// height of right subtree has increased by 1
				// new bf of A is 0, no rebalancing
				A->bf = 0;
				// fix bf on path from A to r
				FixBF(A->RightChild,r,e);
			}
			else 
			{// insertion in left subtree
				// bf of A is +2, rebalance
				AVLNode<E,K> *B = A->LeftChild;
				if (e < B->data)
				{// LL case
					FixBF(B->LeftChild,r,e);
					LLrotate(PA,A,B);
				}
				else 
				{// LR case
					FixBF(B->RightChild,r,e);
					LRrotate(PA,A,B);
				}
			}
		}
	}
	else // A is NULL, no rebalancing
		FixBF(root,r,e);
	
	return *this;
}

template<class E, class K>
AVLtree<E,K>& AVLtree<E,K>::Delete(const K& k, E& e)
{// Delete element with key k and put it in e.
	// Throw BadInput exception if there is no element
	// with key k.
	
	// define a stack to hold path taken from root
	// to physically deleted node
	// we will not run out of stack space unless
	// the number of elements is much more than 2^60
	Stack<AVLNode<E,K>*> S(100);
	
	// set p to point to node with key k
	AVLNode<E,K> *p = root; // search pointer
	while (p && p->data != k)
	{// move to a child of p
		S.Add(p);
		if (k < p->data) 
			p = p->LeftChild;
		else 
			p = p->RightChild;
	}
	if (!p) 
		throw BadInput(); // no element with key k
	
	e = p->data;  // save element to delete
	
	// restructure tree
	// handle case when p has two children
	if (p->LeftChild && p->RightChild) 
	{// two children
		// convert to zero or one child case
		// find largest element in left subtree of p
		S.Add(p);
		AVLNode<E,K> *s = p->LeftChild;
		while (s->RightChild)
		{// move to larger element
			S.Add(s);
			s = s->RightChild;
		}
		
		// move largest from s to p
		p->data = s->data;
		p = s;
	}
	
	// p has at most one child
	// save child pointer in c
	AVLNode<E,K> *c;
	if (p->LeftChild) 
		c = p->LeftChild;
	else 
		c = p->RightChild;
	
	// delete p
	if (p == root) 
		root = c;
	else 
	{// is p a left or right child?
		if (p == S.Top()->LeftChild)
			S.Top()->LeftChild = c;
		else 
			S.Top()->RightChild = c;
	}
	E f = p->data; // f may not equal e
	delete p;
	
	// rebalance tree and correct balance factors
	// use stack to retrace path to root
	// set q to parent of deleted node
	AVLNode<E,K> *q;
	try
	{
		S.Delete(q);
	}
	catch (OutOfBounds)
	{
		return *this;
	} // root was deleted
	
	while (q)
	{
		if (f <= q->data) 
		{
			// deleted from left subtree of q
			// height of left subtree reduced by 1
			q->bf--;
			if (q->bf == -1) // height of q is unchanged
				// nothing more to do
				return *this;
			if (q->bf == -2) 
			{// q is unbalanced
				// classify imbalance and rotate
				AVLNode<E,K> *B = q->RightChild,
					*PA;  // q is A node
				// PA is parent of A
				try 
				{
					S.Delete(PA);
				}
				catch (OutOfBounds)
				{
					PA = 0;
				}       // A is root
				
				switch (B->bf)
				{
				case 0:    // L0 imbalance
					RRrotate(PA,q,B);
					B->bf = 1;
					q->bf = -1;  // q is A node
					return *this;
				case 1:    // L1 imbalance
					RLrotate(PA,q,B);
					break;  // must continue on path to root
				case -1:   // L-1 imbalance
					RRrotate(PA,q,B);
				}
				q = PA;
            }
			else 
			{// q->bf is 0
				try 
				{
					S.Delete(q);
				}
				catch (OutOfBounds)
				{
					return *this;
				}
            }
        }
		else 
		{// f > q->data
			// deleted from right subtree of q
			// height of right subtree reduced by 1
			q->bf++;
			if (q->bf == 1) // height of q is unchanged
				// nothing more to do
				return *this;
			if (q->bf == 2) 
			{// q is unbalanced
				// classify imbalance and rotate
				AVLNode<E,K> *B = q->LeftChild,
					*PA;  // q is A node
				// PA is parent of A
				try
				{
					S.Delete(PA);
				}
				catch (OutOfBounds)
				{
					PA = 0;
				}       // A is root
				
				switch (B->bf) 
				{
				case 0:    // R0 imbalance
					LLrotate(PA,q,B);
					B->bf = -1;
					q->bf = 1;  // q is A node
					return *this;
				case 1:    // R1 imbalance
					LLrotate(PA,q,B);
					break;  // must continue on path to root
				case -1:   // R-1 imbalance
					LRrotate(PA,q,B);
				}
				q = PA;
            }
			else 
			{// q->bf is 0
				try 
				{
					S.Delete(q);
				}
				catch (OutOfBounds)
				{
					return *this;
				}
            }
        }
	}
	return *this;
}

template<class E, class K>
void AVLtree<E,K>::InOutput(AVLNode<E,K> *t)
{// Output in ascending order.
	// Use an inorder traversal.
	if (t) 
	{
		InOutput(t->LeftChild);
		cout << t->data << " ";
		InOutput(t->RightChild);
	}
}

template<class E, class K>
void AVLtree<E,K>::PostOutput(AVLNode<E,K> *t)
{// Output in postorder.
	if (t) 
	{
		PostOutput(t->LeftChild);
		PostOutput(t->RightChild);
		cout << t->data << " ";
	}
}

#endif

⌨️ 快捷键说明

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