AVL树的插入和删除

#pragma once
#include

#include
using namespace std;


template
class AVLTree;

template
class AVLNode
{
	friend class AVLTree;
public:
	AVLNode() :data(0), leftChild(NULL), rightChild(NULL), bf(0)
	{}
	AVLNode(Type d) :data(d), leftChild(NULL), rightChild(NULL), bf(0)
	{}
	~AVLNode()
	{}

private:
	Type data;
	int bf;
	AVLNode*leftChild;
	AVLNode*rightChild;

};
template
class AVLTree
{
public:
	AVLTree() :root(NULL)
	{}
public:
	bool Insert(Type &x)
	{
		return Insert(root, x);
	}
	bool Remove( Type x)
	{
		return Remove(root, x);
	}
	void sort()
	{
		sort(root);
	}
	
protected:
	void sort(AVLNode*t)const
	{
		if (t != NULL)
		{
			sort(t->leftChild);
			cout << t->data << " ";
			sort(t->rightChild);

		}
	}
	bool Insert(AVLNode*&t, Type x)
	{
		AVLNode *p = t;
		AVLNode *pr = NULL;//代表新增加节点的父节点
		stack* >st;
		while (p != NULL)//寻找插入位置,p为根
		{
			pr = p;
			st.push(pr);
			if (x < p->data)
				p = p->leftChild;
			else if (x > p->data)
				p = p->rightChild;
			else
				return false;
		}
		p = new AVLNode(x);
		if (pr == NULL)//空树,新节点为根节点(判断新节点有没有父节点

,即如果没有父节点,就为根节点)
		{
			t = p;
			return true;
		}
		if (x < pr->data)
		{
			pr->leftChild = p;
		}
		else
		{
			pr->rightChild = p;
		}
		while (!st.empty())//比较难理解的是 p,pr 每次循环后与插入值之

间的关系,容易搞混(限于此循环)
		{
			pr = st.top();
			st.pop();
			if (p == pr->leftChild)
				pr->bf--;
			else
				pr->bf++;
			if (pr->bf == 0)
				break;
			else if (pr->bf == 1 || pr->bf == -1)
				p = pr;
			else
			{
				if (pr->bf > 0)
				{
					if (p->bf > 0)
					{
						RotateL(pr);
					}
					else
					{
						RotateRL(pr);

					}
				}
				else
				{
					if (p->bf < 0)
					{
						RotateR(pr);
					}
					else
					{
						RotateLR(pr);
					}
				}
				break;
			}

		}
		if (st.empty())
		{
			t = pr;
		}
		else
		{
			AVLNode*q = st.top();
			if (pr->data < q->data)
				q->leftChild = pr;
			else
				q->rightChild = pr;
		}

	}
	bool Remove(AVLNode*&t, Type &x)//p为要删除的节点
	{
		AVLNode*p = t;
		AVLNode*pr = NULL;
		stack*> st;
		while (p != NULL)//找到要删除的节点p
		{
			if (x == p->data)
				break;
			pr = p;
			st.push(pr);
			if (x > p->data)
				p = p->rightChild;
			else
				p = p->leftChild;
		}
		if (p == NULL)//被删节点不存在
			return false;

		AVLNode*q = NULL;
		if (p->leftChild != NULL&&p->rightChild != NULL)//被删节点有

两个子女,最终转换为只有一个子女
		{
			pr = p;
			st.push(pr);
 			q = p->leftChild;;//中序遍历的前驱(左子树中找最小的

)
			while (q->rightChild != NULL)
			{
				pr = q;
				st.push(pr);
				q = q->rightChild;
			}
			p->data = q->data;//用q的值填补p   发现一个秘密:循环

完后栈的元素为3个,比如依次入栈的元素为11,18,15,执行完这句后栈的元素更改,

更改的元素为18,栈的元素为11,16,15,入栈之后也可以通过指针更改栈的元素,在

最后连接时,使用的出栈元素为更新值
			p = q;//p永远是要删除的节点
		}
		if (p->leftChild != NULL)//1.转换的要删除节点已找到,要将将这

个删除节点转换,即判断这个要删除的节点有没有左右孩子( q指向p左子树代替或右子

树代替,删除p)
			q = p->leftChild;
		else
			q = p->rightChild;

		if (pr == NULL)//被删除节点为根节点
			t = q;
		else
		{
			if (pr->leftChild == p)//2.p(转化的要删节点)的父要重

新连接,即删除节点的父与删除节点的左孩子或者右孩子连接
				pr->leftChild = q;
			else
				pr->rightChild = q;

			

/////////////////////////////////////////////////////////
			//bf(调整平衡因子)
			while (!st.empty())
			{
				pr = st.top();
				st.pop();
				if (pr->leftChild == q&&q != NULL)
					pr->bf++;
				else  if ((pr->rightChild == q&&q != NULL) || 

q == NULL)
					pr->bf--;


				if (pr->bf == 1 || pr->bf == -1)
					break;
				else if (pr->bf == 0)//重新回溯
					q = pr;
				else//较矮子树被缩短
				{
					//q指向较高子树的根
					if (pr->bf > 0)
						q = pr->rightChild;
					else
						q = pr->leftChild;

					if (q->bf == 0)
					{
						if (pr->bf > 0)
						{
							RotateL(pr);
							pr->bf = -1;
							pr->leftChild->bf = 

1;
						}
						else
						{
							RotateR(pr);
							pr->bf = 1;
							pr->rightChild->bf = 

-1;
						}
					}
					else//q->bf和pr->bf相同或相反
					{
						if (q->bf<0 && pr->bf<0)
						{
							RotateR(pr);
						}
						else if (q->bf>0 && pr->bf>0)
						{
							RotateL(pr);
						}
						else if (q->bf<0 && pr->bf>0)
						{
							RotateRL(pr);
						}
						else if (q->bf>0 && pr->bf<0)
						{
							RotateLR(pr);
						}
					}
					break;
				}
			}

			if (st.empty())//调整新根
				t = pr;
			else//链接调整后的
			{
				AVLNode *tmp = st.top();
				if (tmp->data > pr->data)
					tmp->leftChild = pr;
				else
					tmp->rightChild = pr;

			}
		}
		delete p;//p为删除的节点
		return true;
	}
protected:
       //ptr均指不平衡的节点,SUBR,SUBL均为调整后新根的右,左子树
	void RotateL(AVLNode *&ptr)
	{
		AVLNode *subL = ptr;
		ptr = subL->rightChild;
		subL->rightChild = ptr->leftChild;
		ptr->leftChild = subL;
		ptr->bf = subL->bf = 0;
	}
	void RotateR(AVLNode *&ptr)
	{
		AVLNode *subR = ptr;
		ptr = subR->leftChild;
		subR->leftChild = ptr->rightChild;
		ptr->rightChild = subR;
		ptr->bf = subR->bf = 0;
	}
	void RotateLR(AVLNode *&ptr)
	{
		AVLNode *subR = ptr;
		AVLNode *subL = subR->leftChild;
		ptr = subL->rightChild;

		subL->rightChild = ptr->leftChild;
		ptr->leftChild = subL;

		if (ptr->bf <= 0)
			subL->bf = 0;
		else
			subL->bf = -1;

		subR->leftChild = ptr->rightChild;
		ptr->rightChild = subR;


		if (ptr->bf < 0)
			subR->bf = 1;
		else
			subR->bf = 0;

		ptr->bf = 0;
	}
	void RotateRL(AVLNode *&ptr)
	{
		AVLNode*subL = ptr;
		AVLNode*subR = subL->rightChild;
		ptr = subR->leftChild;
		subR->leftChild = ptr->rightChild;
		ptr->rightChild = subR;
		if (ptr->bf >=0)
			subR->bf = 0;
		else
			subR->bf = 1;
		subL->rightChild = ptr->leftChild;
		ptr->leftChild = subL;
		if (ptr->bf >0)
			subL->bf = -1;
		else
			subL->bf = 0;
		ptr->bf = 0;
	}
private:
	AVLNode*root;
};
#include
using namespace std;
void main()
{
	int ar[] = { 16, 3, 7, 11, 9, 26, 18, 14, 15 };
	//int ar[] = {50,30,70,10,35,60,80,32,38};
	//int ar[] = {10, 20};
	int n = sizeof(ar) / sizeof(int);
	AVLTree  avl;
	for (int i = 0; i < n; ++i)
	{
		avl.Insert(ar[i]);
	}
	avl.sort();
	cout << endl;
	avl.Remove(18);
	avl.sort();

	return;
}

 

你可能感兴趣的:(c/c++,数据结构)