STL篇:搜索二叉树,AVL树和红黑树的模拟实现

一、搜索二叉树(二叉排序树)

1、特点:
a.左子树上所有结点的值都小于根结点的值,右子树上所有结点的值都大于根结点的值,左右子树也分别为二叉搜索树
b.最多找高度次:O(N)

2、代码逻辑
a. 没有孩子(托孤)
b. 一个孩子(托孤)
c. 两个孩子(替换法:左子树的最大节点/最右节点,或者右子树的最小节点/最左节点)

#pragma once

namespace key
{
	template  
	struct BSTreeNode
	{
		BSTreeNode* _left;
		BSTreeNode* _right;
		K _key;

		BSTreeNode(const K& key)
			:_left(nullptr)
			,_right(nullptr)
			,_key(key)
		{}
	};

	template
	class BSTree
	{
		typedef BSTreeNode Node;
	public:
		BSTree()
			:_root(nullptr)
		{}

		BSTree(const BSTree& t)
			/*:_root(t._root)*/
		{
			_root = Copy(t._root);
		}

		BSTree& operator=(BSTree t)
		{
			swap(_root, t._root);
			return *this;
		}

		~BSTree()
		{
			Destroy(_root);
		}

		bool Insert(const K& key)
		{
			if (_root == nullptr)
			{
				_root = new Node(key);
				return true;
			}
			Node* parent = nullptr;
			Node* cur = _root;
			while(cur)
			{
				if (key < cur->_key)
				{
					parent = cur;
					cur = cur->_left;
				}
				else if (key > cur->_key)
				{
					parent = cur;
					cur = cur->_right;
				}
				else
				{
					return false;
				}
			}
			cur = new Node(key);
			if (key < parent->_key)
			{
				parent->_left = cur;
			}
			else if (key > parent->_key)
			{
				parent->_right = cur;
			}
			else
			{
				return false;
			}
			return true;
		}

		bool InsertR(const K& key)
		{
			return _InsertR(_root, key);
		}

		bool find(const K& key)
		{
			Node* cur = _root;
			while (cur)
			{
				if (key < cur->_key)
				{
					cur = cur->_left;
				}
				else if (key > cur->_key)
				{
					cur = cur->_right;
				}
				else
				{
					return true;
				}
			}
			return false;
		}

		bool FindR(const K& key)
		{
			return _FindR(_root, key);
		}

		bool Erase(const K& key)
		{
			Node* parent = nullptr;
			Node* cur = _root;
			while (cur)
			{
				if (key < cur->_key)
				{
					parent = cur;
					cur = cur->_left;
				}
				else if (key > cur->_key)
				{
					parent = cur;
					cur = cur->_right;
				}
				else
				{
					//左为空
					if (cur->_left == nullptr)
					{
						if (cur == _root)
						{
							_root = cur->_right;
						}
						else
						{
							if (parent->_right == cur)
							{
								parent->_right = cur->_right;
							}
							else
							{
								parent->_left = cur->_right;
							}
						}
					}
					//右为空
					else if (cur->_right == nullptr)
					{
						if (cur == _root)
						{
							_root = cur->_left;
						}
						else
						{
							if (parent->_left == cur)
							{
								parent->_left = cur->_left;
							}
							else
							{
								parent->_right = cur->_left;
							}
						}
					}
					//左右都不为空
					else
					{
						Node* parnet = cur;
						Node* leftmax = cur->_left;//找左枝最大节点
						while (leftmax->_right)
						{
							parent = leftmax;
							leftmax = leftmax->_right;
						}
						swap(leftmax->_key, cur->_key);
						if (parent->_left == leftmax)
						{
							parent->_left = leftmax->_left;
						}
						else
						{
							parent->_right = leftmax->_left;
						}
						cur = leftmax;
					}
					delete cur;
					return true;
				}
			}
		}

		bool EraseR(const K& key)
		{
			return _EraseR(_root, key);
		}

		void Inorder()
		{
			_Inorder(_root);
			cout << endl;
		}

	private:
		Node* Copy(Node* root)
		{
			if(root == nullptr)
			{
				return nullptr;
			}
			Node* copyroot = new Node(root->_key);
			Copy(root->_left);
			Copy(root->_right);
			return copyroot;
		}

		void Destroy(Node* root)
		{
			if (root == nullptr)
			{
				return;
			}
			Destroy(root->_left);
			Destroy(root->_right);
			delete root;
			root = nullptr;
		}

		void _Inorder(Node* root)
		{
			if (root == nullptr)
			{
				return;
			}
			_Inorder(root->_left);
			cout << root->_key << " ";
			_Inorder(root->_right);
		}

		bool _FindR(Node* root, const K& key)
		{
			if (root == nullptr)
			{
				return false;
			}

			if (key < root->_key)
			{
				FindR(root->_left);
			}
			else if (key > root->_key)
			{
				FindR(root->_right);
			}
			else
			{
				return true;
			}
		}

		bool _InsertR(Node*& root, const K& key)
		{
			if (root == nullptr)
			{
				root = new Node(key);
				return true;
			}

			if (key < root->_key)
			{
				return _InsertR(root->_left, key);
			}
			else if (key > root->_key)
			{
				return _InsertR(root->_right, key);
			}
			else
			{
				return false;
			}
		}

		bool _EraseR(Node*& root, const K& key)
		{
			if (root == nullptr)
			{
				return false;
			}
			if (key < root->_key)
			{
				return _EraseR(root->_left, key);
			}
			else if (key > root->_key)
			{
				return _EraseR(root->_right, key);
			}
			else
			{
				Node* del = root;
				//左为空
				if (root->_left == nullptr)
				{
					root = root->_right;
				}
				//右为空
				else if (root->_right == nullptr)
				{
					root = root->_left;
				}
				//左右都不为空
				else
				{
					Node* leftmax = root->_left;//找左枝最大节点
					while (leftmax->_right)
					{
						leftmax = leftmax->_right;
					}
					swap(leftmax->_key, root->_key);
					return _EraseR(root->_left, key);
				}
				delete del;
				return true;
			}
		}
	private:
		Node* _root;
	};
}

二、AVL树(高度平衡二叉搜索树)

1、特点:
a.左右子树都是avl树
b.左右子树高度之差(简称平衡因子)的绝对值不超过1(平衡因子=右子树的高度-左子树的高度)

2、代码逻辑
新增在左,parent平衡因子--。
新增在右,parent平衡因子++。
更新后parent平衡因子=0,说明parent所在的子数的高度不变,不会再影响祖先,不用再继续(沿着到root的路径)往上更新。
更新后parent平衡因子=-1/1,说明parent所在的子数的高度变化,会影响祖先,需要继续(沿着到root的路径)往上更新。
更新后parent平衡因子=-2/2,说明parent所在的子树的高度变化且不平衡,对parent所在的子树进行旋转,使之平衡。

#pragma once

#include
#include
using namespace std;

template
struct AVLTreeNode
{
	pair _kv;
	AVLTreeNode* _left;
	AVLTreeNode* _right;
	AVLTreeNode* _parent;
	int _bf;

	AVLTreeNode(const pair& kv)
		:_kv(kv)
		,_left(nullptr)
		,_right(nullptr)
		,_parent(nullptr)
		,_bf(0)
	{}
};

template
struct AVLTree
{
	typedef AVLTreeNode Node;
public:
	bool Insert(const pair& kv)
	{
		if (_root == nullptr)
		{
			_root = new Node(kv);
			return true;
		}

		Node* cur = _root;
		Node* parent = nullptr;

		while (cur)
		{
			if (kv.first < cur->_kv.first)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (kv.first > cur->_kv.first)
			{
				parent = cur;
				cur = cur->_right;
			}
			else
			{
				return false;
			}
		}
		cur = new Node(kv);
		
		if (kv.first < parent->_kv.first)
		{
			parent->_left = cur;
		}
		else
		{
			parent->_right = cur;
		}

		cur->_parent = parent;

		//控制平衡:更新平衡因子
		while (parent)
		{
			if (parent->_left == cur)
			{
				parent->_bf--;
			}
			else if (parent->_right == cur)
			{
				parent->_bf++;
			}
			if (parent->_bf == 0)
			{
				break;
			}
			else if (parent->_bf == -1 || parent->_bf == 1)
			{
				//继续向上更新
				cur = parent;
				parent = parent->_parent;
			}
			else if (parent->_bf == -2 || parent->_bf == 2)
			{
				if (parent->_bf == -2 && cur->_bf == -1)
				{
					RotateR(parent);
				}
				else if (parent->_bf == 2 && cur->_bf == 1)
				{
					RotateL(parent);
				}
				else if (parent->_bf == -2 && cur->_bf == 1)
				{
					RotateLR(parent);
				}
				else if (parent->_bf == 2 && cur->_bf == -1)
				{
					RotateRL(parent);
				}
				break;
			}
			else
			{
				assert(false);
			}
		}
		return true;
	}

	void RotateL(Node* parent)
	{
		Node* cur = parent->_right;
		Node* curleft = cur->_left;
		parent->_right = curleft;
		if (curleft)
		{
			curleft->_parent = parent;
		}
		cur->_left = parent;

		Node* ppnode = parent->_parent;
		parent->_parent = cur;

		if (parent == _root)
		{
			_root = cur;
			cur->_parent = nullptr;
		}
		else
		{
			if (parent == ppnode->_left)
			{
				ppnode->_left = cur;
			}
			else
			{
				ppnode->_right = cur;
			}
			cur->_parent = ppnode;
		}
		parent->_bf = cur->_bf = 0;
	}

	void RotateR(Node* parent)
	{
		Node* cur = parent->_left;
		Node* curright = cur->_right;

		parent->_left = curright;
		if (curright)
		{
			curright->_parent = parent;
		}
		Node* ppnode = parent->_parent;
		cur->_right = parent;
		parent-> _parent = cur;

		if (parent == _root)
		{
			_root = cur;
			cur->_parent = nullptr;
		}
		else
		{
			if (ppnode->_left == parent)
			{
				ppnode->_left = cur;
			}
			else
			{
				ppnode->_right = cur;
			}
			cur->_parent = ppnode;
		}

		parent->_bf = cur->_bf = 0;
	}

	void RotateRL(Node* parent)
	{
		Node* cur = parent->_right;
		Node* curleft = cur->_left;
		int bf = curleft->_bf;

		RotateR(cur);
		RotateL(parent);

		if (bf == 0)
		{
			parent->_bf = 0;
			cur->_bf = 0;
			curleft->_bf = 0;
		}
		else if (bf == -1)
		{
			parent->_bf = 0;
			cur->_bf = 1;
			curleft->_bf = 0;
		}
		else if (bf == 1)
		{
			parent->_bf = -1;
			cur->_bf = 0;
			curleft->_bf = 0;
		}
		else
		{
			assert(false);
		}
	}

	void RotateLR(Node* parent)
	{
		Node* cur = parent->_left;
		Node* curright = cur->_right;

		RotateL(cur);
		RotateR(parent);
		int bf = curright->_bf;

		if (bf == 0)
		{
			parent->_bf = 0;
			cur->_bf = 0;
			curright->_bf = 0;
		}
		else if (bf == -1)
		{
			parent->_bf = 1;
			cur->_bf = 0;
			curright->_bf = 0;
		}
		else if (bf == 1)
		{
			parent->_bf = 0;
			cur->_bf = -1;
			curright->_bf = 0;
		}
		else
		{
			assert(false);
		}
	}

	int Height()
	{
		return _Height(_root);
	}

	bool IsBalance()
	{
		return _IsBalance(_root);
	}

private:
	int _Height(Node* root)
	{
		if (root == nullptr)
		{
			return 0;
		}

		int LeftHeight = _Height(root->_left);
		int RightHeight = _Height(root->_right);

		return LeftHeight > RightHeight ? LeftHeight + 1 : RightHeight + 1;
	}

	bool _IsBalance(Node* root)
	{
		if (root == nullptr)
		{
			return true;
		}

		int LeftHeight = _Height(root->_left);
		int RightHeight = _Height(root->_right);
		if (RightHeight - LeftHeight != root->_bf)
		{
			cout << "平衡因子异常:" << _root->_kv.first << "->" << _root->_bf << endl;
			return false;
		}

		return abs(RightHeight - LeftHeight) < 2
			&& _IsBalance(root->_left)
			&& _IsBalance(root->_right);
	}

private:
	Node* _root = nullptr;
};

三、红黑树

1、红黑树特点:
a.每个节点不是黑色就是红色(根节点是黑色的,NIL叶节点都为黑色)
b.如果一个节点是红色的,则它的两个孩子节点必须是黑色的(任何路径没有连续红节点)
c.每条路径上都包含相同数量的黑节点
b.黑色节点占比>=1/2
e.最长路径不超过最短路径的2倍(近似平衡)(从根到空节点NIL算一条路径),最短全黑,最长一黑一红相间

2、代码逻辑
红黑树插入关键看uncle
1、uncle存在且为红,变色+继续向上更新
2、uncle不存在,uncle存在且为黑,旋转+变色

#pragma once

#include

using namespace std;

enum Color
{
	RED,
	BLACK
};

template
struct RBTreeNode
{
	RBTreeNode* _left;
	RBTreeNode* _right;
	RBTreeNode* _parent;

	pair _kv;
	Color _col;

	RBTreeNode(const pair& kv)
		: _left(nullptr)
		, _right(nullptr)
		, _parent(nullptr)
		, _kv(kv)
		,_col(RED)
	{}
};

template
struct RBTree
{
	typedef RBTreeNode Node;
public:
	bool Insert(const pair& kv)
	{
		if (_root == nullptr)
		{
			_root = new Node(kv);
			_root->_col = BLACK;
			return true;
		}

		Node* cur = _root;
		Node* parent = nullptr;

		while (cur)
		{
			if (kv.first < cur->_kv.first)
			{
				parent = cur;
				cur = cur->_left;
			}
			else if (kv.first > cur->_kv.first)
			{
				parent = cur;
				cur = cur->_right;
			}
			else
			{
				return false;
			}

			cur = new Node(kv);
			cur->_col = RED;
			if (kv.first < parent->_kv.first)
			{
				parent->_left = cur;
			}
			else
			{
				parent->_right = cur;
			}

			cur->_parent = parent;

			//如果父亲为黑,无需处理

			//如果父亲为红
			while (parent && parent->_col == RED)
			{
				Node* grandparent = parent->_parent;
				//Node* uncle;//有可能没有叔叔节点

				if (grandparent->_left == parent)
				{
					Node* uncle = grandparent->_right;
					//叔叔节点存在且为红
					if (uncle && uncle->_col == RED)
					{
						//       g(R)
						// 
						//   p(B)    u(B)
						parent->_col = uncle->_col = BLACK;
						grandparent->_col = RED;
						//向上处理
						cur = grandparent;
						parent = cur->_parent;
					}
					//叔叔节点为黑或者叔叔节点不存在
					else
					{
						//        g(B)             p(B)    
						//    p(R)   (u(B)) -> c(R)    g(R)
						//c(R)                             (u)     
						if (cur == parent->_left)
						{
							RotateR(grandparent);
							parent->_col = BLACK;
							grandparent->_col = RED;
						}
						//     g(B)           c(B)
						//p(R)        ->       
						//     c(R)       p(R)    g(R)
						else
						{
							RotateL(parent);
							RotateR(grandparent);
							cur->_col = BLACK;
							grandparent->_col = RED;
						}
						break;
					}
				}
				else
				{
					Node* uncle = grandparent->_left;
					//叔叔节点存在且为红
					if (uncle && uncle->_col == RED)
					{
						//       g(R)
						// 
						//   u(B)    p(B)
						parent->_col = uncle->_col = BLACK;
						grandparent->_col = RED;
						//向上处理
						cur = grandparent;
						parent = cur->_parent;
					}
					//叔叔节点为黑或者叔叔节点不存在
					else
					{
						//        g(B)                   p(B)    
						// (u(R))    p(B)     ->    g(R)    c(R)
						//                c(R)    (u)
						if (cur == parent->_right)
						{
							RotateL(grandparent);
							parent->_col = BLACK;
							grandparent->_col = RED;
						}
						//g(B)                    c(B)
						//      p(R)    ->       
						//c(R)                g(R)    p(R)
						else
						{
							RotateR(parent);
							RotateL(grandparent);
							cur->_col = BLACK;
							grandparent->_col = RED;
						}
					}
				}
			}
		}
		_root->_col = BLACK;
		return true;
	}

	void RotateL(Node* parent)
	{
		Node* cur = parent->_right;
		Node* curleft = cur->_left;

		parent->_right = curleft;
		if (curleft)
		{
			curleft->_parent = parent;
		}

		cur->_left = parent;

		Node* ppnode = parent->_parent;

		parent->_parent = cur;


		if (parent == _root)
		{
			_root = cur;
			cur->_parent = nullptr;
		}
		else
		{
			if (ppnode->_left == parent)
			{
				ppnode->_left = cur;
			}
			else
			{
				ppnode->_right = cur;

			}

			cur->_parent = ppnode;
		}
	}


	void RotateR(Node* parent)
	{
		Node* cur = parent->_left;
		Node* curright = cur->_right;

		parent->_left = curright;
		if (curright)
			curright->_parent = parent;

		Node* ppnode = parent->_parent;
		cur->_right = parent;
		parent->_parent = cur;

		if (ppnode == nullptr)
		{
			_root = cur;
			cur->_parent = nullptr;
		}
		else
		{
			if (ppnode->_left == parent)
			{
				ppnode->_left = cur;
			}
			else
			{
				ppnode->_right = cur;
			}

			cur->_parent = ppnode;
		}
	}

	int Height()
	{
		return Height(_root);
	}

	int Height(Node* root)
	{
		if (root == nullptr)
			return 0;

		int leftHeight = Height(root->_left);
		int rightHeight = Height(root->_right);

		return leftHeight > rightHeight ? leftHeight + 1 : rightHeight + 1;
	}

	//判断颜色:根为黑色,不能出现连续红色节点
	bool checkcolor(Node* root, int blacknum, int benchmark)
	{
		if (root == nullptr)
		{
			if (blacknum != benchmark)
			{
				return false;
			}
			return true;
		}

		if (root->_col == BLACK)
		{
			++blacknum;
		}

		if (root->_col == RED && root->_parent && root->_parent->_col == RED)
		{
			cout << root->_kv.first << "出现连续红色节点" << endl;
			return false;
		}
		return checkcolor(root->_left, blacknum, benchmark)
			&& checkcolor(root->_right, blacknum, benchmark);
	}

	bool IsBalance()
	{
		return _IsBalance(_root);
	}

	bool _IsBalance(Node* root)
	{
		if (root == nullptr)
		{
			return true;
		}

		if (root->_col != BLACK)
		{
			return false;
		}

		int benchmark = 0;
		Node* cur = root;
		while (cur)
		{
			if (cur->_col == BLACK)
			{
				benchmark++;
			}
			cur = cur->_left;
		}

		return checkcolor(root, 0, benchmark);
	}
private:
	Node* _root = nullptr;

};

总结:AVL树和红黑树性能是同一量级的,但是AVL树控制严格平衡是要付出代价的,插入和删除需要进行大量的旋转
 

 

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