c++之AVL树

AVL树及其基本操作
1.AVL树概念

二叉搜索树岁可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于顺序表中搜元素,效率低下。AVL树是一颗平衡二叉搜索树,在AVL树中,任何结点的两个子树的高度差的绝对值不超过1(需对树中的结点进行调整),即可降低树的高度,从而减少平均搜索长度。

2.AVL树的性质

它的左右子树都是AVL树

左右子树的高度差(简称平衡因子)的绝对值不超过1(-1/0/1)

如果其高度保持在O(logn),搜索时的时间复杂度为O(logn)。

3.AVL树的基本操作

3.1AVL树结点的定义:

struct AVLTreeNode {
	AVLTreeNode(const T&data=T())
		:_pLeft(nullptr)
		,_pRight(nullptr)
		,_pParent(nullptr)
		,_data(data)
		,_bf(0)
	{}
	AVLTreeNode <T>* _pLeft;
	AVLTreeNode<T>* _pRight;
	AVLTreeNode<T>* _pParent;
	T _data;
	int _bf;
};

3.2AVL树的插入
AVL树的插入分为两步:按照二叉搜索树的方式插入 调节结点的平衡因子

	bool Insert(const T& data) {
		if (_pRoot == nullptr) {
			_pRoot = new Node(data);
			return true;
		}
		Node* pCur = _pRoot;
		Node* pParent = nullptr;
		while (pCur) {
			pParent = pCur;
			if (data < pCur->_data) {
				pCur = pCur->_pLeft;
			}
			else if (data > pCur->_data) {
				pCur = pCur->_pRight;
			}
			else {
				return false;
			}
		}
		pCur = new Node(data);
		if (data < pParent->_data) {
			pParent->_pLeft = pCur;
		}
		else {
			pParent->_pRight = pCur;
		}
		pCur->_pParent = pParent;
		while (pParent) {
			if (pCur == pParent->_pRight) {
				pParent->_bf++;
			}
			else {
				pParent->_bf--;
			}
			if (0 == pParent->_bf) {
				break;
			}
			else if (1 == pParent->_bf || -1 == pParent->_bf) {
				pCur = pParent;
				pParent = pCur->_pParent;
			}
			else {
				if (pParent->_bf == 2) {
					if (pCur->_bf == 1) {
						RotateL(pParent);
					}
					else {
						RotateRL(pParent);
					}
				}
				else {
					if (pCur->_bf == -1) {
						RotateR(pParent);
					}
					else {
						RotateLR(pParent);
					}
				}
				break;
			}
		}
		return true;
	}

3.3AVL树的旋转
3.3.1:左单旋
在这里插入图片描述
代码实现:

	void RotateL(Node* pParent) {
		Node* pSubR = pParent->_pRight;
		Node* pSubRL = pSubR->_pLeft;
		pParent->_pRight = pSubRL;
		if (pSubRL) {
			pSubRL->_pParent = pParent;
		}
		pSubR->_pLeft = pParent;
		Node* pPParent = pParent->_pParent;
		pSubR->_pParent = pPParent;
		pParent->_pParent = pSubR;
		if (nullptr == pPParent) {
			_pRoot = pSubR;
		}
		else {
			if (pPParent->_pLeft == pParent) {
				pPParent->_pLeft = pSubR;
			}
			else {
				pPParent->_pRight = pSubR;
			}
		}
		pParent->_bf = pSubR->_bf = 0;
	}

3.3.2 右单旋
在这里插入图片描述
代码实现:

	void RotateR(Node* pParent) {
		Node* pSubL = pParent->_pLeft;
		Node* pSubLR = pSubL->_pRight;
		pParent->_pLeft = pSubLR;
		if (pSubLR) {
			pSubLR->_pParent = pParent;
		}
		pSubL->_pRight = pParent;
		Node* pPParent = pParent->_pParent;
		pParent->_pParent = pSubL;
		pSubL->_pParent = pPParent;
		if (pPParent == nullptr) {
			_pRoot = pSubL;
		}
		else {
			if (pPParent->_pLeft == pParent) {
				pPParent->_pLeft = pSubL;
			}
			else {
				pPParent->_pRight = pSubL;
			}
		}
		pParent->_bf = pSubL->_bf = 0;
	}

3.3.3先左单旋再右单旋
在这里插入图片描述
代码实现

void RotateLR(Node* pParent) {
		Node* pSubL = pParent->_pLeft;
		Node* pSubLR = pSubL->_pRight;
		int bf = pSubLR->_bf;
		RotateL(pParent->_pLeft);
		RotateR(pParent);
		if (bf == -1) {
			pParent->_bf = 1;
		}
		else if (bf == 1) {
			pSubL->_bf = -1;
		}
	}

3.3.4先右单旋再左单旋
在这里插入图片描述
代码实现:

	void RotateRL(Node* pParent) {
		Node* pSubR = pParent->_pRight;
		Node* pSubRL = pSubR->_pLeft;
		int bf = pSubRL->_bf;
		RotateR(pParent->_pRight);
		RotateL(pParent);
		if (bf == -1) {
			pSubR->_bf = 1;
		}
		else if(bf==1){
			pParent->_bf = -1;
		}
	}

4.AVL树的验证

AVL树的验证分为两步:
(1):验证其为二叉搜索树
如果中序遍历可以得到一个有序的序列,就说明为二叉搜索树
(2):验证其为平衡时:
每个节点子树的高度差不超过1
结点的平衡因子是否计算正确

bool _IsAVLTree(Node* pRoot) {
		if (pRoot == nullptr) {
			return true;
		}
		int leftHeigth = _Heigth(pRoot->_pLeft);
		int rightHeigth = _Heigth(pRoot->_pRight);
		if (abs(leftHeigth - rightHeigth) > 1 || rightHeigth - leftHeigth != pRoot->_bf) {
			return false;
		}
		return _IsAVLTree(pRoot->_pLeft) && _IsAVLTree(pRoot->_pRight);
	}
	size_t _Heigth(Node* pRoot) {
		if (pRoot == nullptr) {
			return 0;
		}
		size_t leftHeigth = _Heigth(pRoot->_pLeft);
		size_t rightHeigth = _Heigth(pRoot->_pRight);
		return leftHeigth > rightHeigth ? leftHeigth+1 : rightHeigth+1;
	}

5.AVL树的实现

#pragma once
#include<iostream>
using namespace std;
template<class T>
struct AVLTreeNode {
	AVLTreeNode(const T&data=T())
		:_pLeft(nullptr)
		,_pRight(nullptr)
		,_pParent(nullptr)
		,_data(data)
		,_bf(0)
	{}
	AVLTreeNode <T>* _pLeft;
	AVLTreeNode<T>* _pRight;
	AVLTreeNode<T>* _pParent;
	T _data;
	int _bf;
};
template<class T>
class AVLTree {
	typedef AVLTreeNode<T>Node;
public:
	AVLTree()
		:_pRoot(nullptr)
	{}
	bool Insert(const T& data) {
		if (_pRoot == nullptr) {
			_pRoot = new Node(data);
			return true;
		}
		Node* pCur = _pRoot;
		Node* pParent = nullptr;
		while (pCur) {
			pParent = pCur;
			if (data < pCur->_data) {
				pCur = pCur->_pLeft;
			}
			else if (data > pCur->_data) {
				pCur = pCur->_pRight;
			}
			else {
				return false;
			}
		}
		pCur = new Node(data);
		if (data < pParent->_data) {
			pParent->_pLeft = pCur;
		}
		else {
			pParent->_pRight = pCur;
		}
		pCur->_pParent = pParent;
		while (pParent) {
			if (pCur == pParent->_pRight) {
				pParent->_bf++;
			}
			else {
				pParent->_bf--;
			}
			if (0 == pParent->_bf) {
				break;
			}
			else if (1 == pParent->_bf || -1 == pParent->_bf) {
				pCur = pParent;
				pParent = pCur->_pParent;
			}
			else {
				if (pParent->_bf == 2) {
					if (pCur->_bf == 1) {
						RotateL(pParent);
					}
					else {
						RotateRL(pParent);
					}
				}
				else {
					if (pCur->_bf == -1) {
						RotateR(pParent);
					}
					else {
						RotateLR(pParent);
					}
				}
				break;
			}
		}
		return true;
	}
	void InOrder() {
		_InOrder(_pRoot);
	}
	Node* LeftMost() {
		if (_pRoot == nullptr) {
			return NULL;
		}
		Node* pCur = _pRoot;
		while (pCur->_pLeft) {
			pCur = pCur->_pLeft;
		}
		return pCur;
	}
	Node* RightMost() {
		if (_pRoot == nullptr) {
			return NULL;
		}
		Node* pCur = _pRoot;
		while (pCur->_pRight) {
			pCur = pCur->_pRight;
		}
		return pCur;
	}
	bool IsAVLTree() {
		return _IsAVLTree(_pRoot);
	}
private:
	void RotateL(Node* pParent) {
		Node* pSubR = pParent->_pRight;
		Node* pSubRL = pSubR->_pLeft;
		pParent->_pRight = pSubRL;
		if (pSubRL) {
			pSubRL->_pParent = pParent;
		}
		pSubR->_pLeft = pParent;
		Node* pPParent = pParent->_pParent;
		pSubR->_pParent = pPParent;
		pParent->_pParent = pSubR;
		if (nullptr == pPParent) {
			_pRoot = pSubR;
		}
		else {
			if (pPParent->_pLeft == pParent) {
				pPParent->_pLeft = pSubR;
			}
			else {
				pPParent->_pRight = pSubR;
			}
		}
		pParent->_bf = pSubR->_bf = 0;
	}
	void RotateR(Node* pParent) {
		Node* pSubL = pParent->_pLeft;
		Node* pSubLR = pSubL->_pRight;
		pParent->_pLeft = pSubLR;
		if (pSubLR) {
			pSubLR->_pParent = pParent;
		}
		pSubL->_pRight = pParent;
		Node* pPParent = pParent->_pParent;
		pParent->_pParent = pSubL;
		pSubL->_pParent = pPParent;
		if (pPParent == nullptr) {
			_pRoot = pSubL;
		}
		else {
			if (pPParent->_pLeft == pParent) {
				pPParent->_pLeft = pSubL;
			}
			else {
				pPParent->_pRight = pSubL;
			}
		}
		pParent->_bf = pSubL->_bf = 0;
	}
	void RotateRL(Node* pParent) {
		Node* pSubR = pParent->_pRight;
		Node* pSubRL = pSubR->_pLeft;
		int bf = pSubRL->_bf;
		RotateR(pParent->_pRight);
		RotateL(pParent);
		if (bf == -1) {
			pSubR->_bf = 1;
		}
		else if(bf==1){
			pParent->_bf = -1;
		}
	}
	void RotateLR(Node* pParent) {
		Node* pSubL = pParent->_pLeft;
		Node* pSubLR = pSubL->_pRight;
		int bf = pSubLR->_bf;
		RotateL(pParent->_pLeft);
		RotateR(pParent);
		if (bf == -1) {
			pParent->_bf = 1;
		}
		else if (bf == 1) {
			pSubL->_bf = -1;
		}
	}
	Node* _InOrder(Node*pRoot) {
		if (pRoot) {
			_InOrder(pRoot->_pLeft);
			cout << pRoot->_data << " ";
			_InOrder(pRoot->_pRight);
		}
		return _pRoot;
	}
	bool _IsAVLTree(Node* pRoot) {
		if (pRoot == nullptr) {
			return true;
		}
		int leftHeigth = _Heigth(pRoot->_pLeft);
		int rightHeigth = _Heigth(pRoot->_pRight);
		if (abs(leftHeigth - rightHeigth) > 1 || rightHeigth - leftHeigth != pRoot->_bf) {
			return false;
		}
		return _IsAVLTree(pRoot->_pLeft) && _IsAVLTree(pRoot->_pRight);
	}
	size_t _Heigth(Node* pRoot) {
		if (pRoot == nullptr) {
			return 0;
		}
		size_t leftHeigth = _Heigth(pRoot->_pLeft);
		size_t rightHeigth = _Heigth(pRoot->_pRight);
		return leftHeigth > rightHeigth ? leftHeigth+1 : rightHeigth+1;
	}
private:
	Node* _pRoot;
};
void TestAVLTree() {
	int a[] = { 4, 2, 6, 1, 3, 5, 15, 7, 16, 14 };
	AVLTree<int>t;
	for (auto& e : a) {
		t.Insert(e);
	}
	t.InOrder();
	cout << endl;
	cout << t.LeftMost()->_data << endl;
	cout << t.RightMost()->_data << endl;
	if (t.IsAVLTree()) {
		cout << " is AVLTree" << endl;
	}
	else {
		cout << "is not AVLTree" << endl;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值