1 Star 0 Fork 1

蓝俊/C++练习

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
AVLTree.h 6.04 KB
一键复制 编辑 原始数据 按行查看 历史
蓝俊 提交于 4年前 . AVLTree树实现
#include<iostream>
#include<assert.h>
using namespace std;
template<class K, class V>
struct AVLTreeNode
{
AVLTreeNode<K, V>* _left; //左孩子
AVLTreeNode<K, V>* _right; //右孩子
AVLTreeNode<K, V>* _parent; //父亲结点
pair<K, V> _Kv; //键值
int _bf; //平衡因子
//构造函数
AVLTreeNode(const pair<K, V>& Kv)
:_left(nullptr)
, _right(nullptr)
, _parent(nullptr)
, _Kv(Kv)
, _bf(0)
{}
};
template<class K, class V>
class AVLTree
{
typedef AVLTreeNode<K, V> Node;
private:
void Destroy(Node *root)
{
if (!root) return;
Destroy(root->_left);
Destroy(root->_right);
delete root;
}
public:
//成员函数
AVLTree()
:_root(nullptr)
{}
//析构函数
~AVLTree()
{
Destroy(_root);
_root = nullptr;
}
Node* copy(Node* cp)
{
if (!cp) return nullptr;
Node* newnode = new Node(cp->_Kv);
newnode->_left = copy(cp->_left);
newnode->_right = copy(cp->_right);
return newnode;
}
//拷贝构造
AVLTree(const AVLTree<K, V>& job)
{
if(&job != this)
_root = copy(job._root);
}
void operator=(AVLTree<K, V> tmp)
{
if (&tmp != this)
swap(tmp._root, this->_root);
}
V& operator[](const K& key)
{
return (Insert(make_pair(key, V())).first)->_Kv.second;
}
pair<Node* ,bool> Insert(const pair<K, V>& kv)
{
if (!_root)
{
_root = new Node(kv); //初始根节点
return make_pair(_root, true);
}
Node* cur = _root;
Node* parent = _root;
while (cur)
{
if (cur->_Kv.first > kv.first) //比根结点的key值小,
{
parent = cur;
cur = cur->_left;
}
else if (cur->_Kv.first < kv.first)//比根结点的key值大,
{
parent = cur;
cur = cur->_right;
}
else
{
return make_pair(cur, true); //如果已经存在key值那么就返回那个与他相同的结点
}
}
//开始插入
cur = new Node(kv);
Node *newNode = cur;
if (parent->_Kv.first > kv.first) //新插入的结点key值比根节点小就插入到左子树
{
parent->_left = newNode;
newNode->_parent = parent;
}
else //新插入的结点key值比根节点大就插入到右子树
{
parent->_right = newNode;
newNode->_parent = parent;
}
//更新祖先路径的所以结点的平衡因子
/*
总结五种情况:
1、新增结点出现在父结点的左边,平衡因子减减
2、新增结点出现在父结点的右边,平衡因子加加
3、父亲的平衡因子为0就不再调整
4、父亲结点的平衡因子为1或者-1继续调整
5、父亲结点的平衡因子为2或者-2那就旋转
*/
Node* retnode = cur;
while (parent)
{
if (parent->_left == cur) parent->_bf--;
if (parent->_right == cur) parent->_bf++;
if (parent->_bf == 0) break;
if (parent->_bf == -1 || parent->_bf == 1)
{
cur = parent;
parent = parent->_parent;
}
else if (parent->_bf == -2 || parent->_bf == 2)
{
//左
if (parent->_bf == -2)
{
if (cur->_bf == -1) RotateR(parent);
else RotateLR(parent);
}
else //右 parent->_bf == 2
{
if (cur->_bf == 1) RotateL(parent);
else RotateRL(parent);
}
break;
}
}
return make_pair(retnode, true); //返回进入进去的结点
}
//右左旋转
void RotateRL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
int bf = subRL->_bf;
RotateR(parent->_right);
RotateL(parent);
if (bf == -1) //如果新增结点在左边
{
parent->_bf = 0;
subR->_bf = 1;
subRL->_bf = 0;
}
else if (bf == 1) //如果新增结点在右边
{
parent->_bf = -1;
subR->_bf = 0;
subRL->_bf = 0;
}
else if (bf == 0)
{
subR->_bf = 0;
subRL->_bf = 0;
parent->_bf = 0;
}
}
//左右旋转
void RotateLR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
int bf = subLR->_bf;
RotateL(parent->_left);
RotateR(parent);
if (bf == -1)
{
parent->_bf = 1;
subLR->_bf = 0;
subL->_bf = 0;
}
else if (bf == 1)
{
subL->_bf = -1;
subLR->_bf = 0;
parent->_bf = 0;
}
else if(bf == 0)
{
parent->_bf = 0;
subLR->_bf = 0;
subL->_bf = 0;
}
}
//左单旋
void RotateL(Node* parent)
{
Node* subR = parent->_right;
Node* subRL = subR->_left;
parent->_right = subRL;
if (subRL) subRL->_parent = parent;
subR->_left = parent;
Node* parent_parent = parent->_parent;
parent->_parent = subR;
if (_root == parent)
{
_root = subR;
_root->_parent = nullptr;
}
else
{
if (parent_parent->_left == parent) parent_parent->_left = subR;
else parent_parent->_right = subR;
subR->_parent = parent_parent;
}
subR->_bf = parent->_bf = 0;
}
//右单旋
void RotateR(Node* parent)
{
Node* subL = parent->_left;
Node* subLR = subL->_right;
parent->_left = subLR;
if (subLR) subLR->_parent = parent; //防止subLR为nullptr
subL->_right = parent;
Node* parent_parent = parent->_parent; //指针备份
parent->_parent = subL;
if (_root == parent) //如果parent就是树的根
{
_root = subL; //subL取代parent
_root->_parent = nullptr;
}
else //如果parent并不是树的根
{
if (parent_parent->_left == parent) parent_parent->_left = subL;
else parent_parent->_right = subL;
subL->_parent = parent_parent; //subL去做parent_parent的孩子
}
//调节平衡因子
subL->_bf = parent->_bf = 0;
}
int height(Node* root) //求高度
{
return !root ? 0
: max(height(root->_left),
height(root->_right)) + 1;
}
Node* Find(const K& key)
{
Node* cur = _root;
while (cur)
{
if (key > cur->_Kv.first) cur = cur->_right; //左子树
else if (key < cur->_Kv.first) cur = cur->_left; //右子树
else return cur;
}
return nullptr;
}
void Inorder()
{
_Inorder(_root);
cout << endl;
}
bool IsAVLTree()
{
return _IsAVLTree(_root);
}
private:
void _Inorder(Node* root)
{
if (!root) return;
_Inorder(root->_left);
cout << root->_Kv.first << ":" << root->_Kv.second << endl;
_Inorder(root->_right);
}
//判断是不是平衡二叉树
bool _IsAVLTree(Node* root)
{
if (!root) return true;
int left = height(root->_left);
int right = height(root->_right);
//检查平衡因子
if (right - left != root->_bf)
{
printf("错误的平衡因子 %d :%d\n", root->_Kv.first, root->_Kv.second);
return false;
}
return (abs(right - left) < 2)
&& _IsAVLTree(root->_left)
&& _IsAVLTree(root->_right);
}
private:
Node* _root;
};
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/mozart-01/c-practice.git
git@gitee.com:mozart-01/c-practice.git
mozart-01
c-practice
C++练习
master

搜索帮助