自己写的简单AVL树实现,有BUG或意见欢迎留言
#ifndef SIMPLEAVLTREE_H
#define SIMPLEAVLTREE_H
#include "simplequeue.h"
#include "simplestring.h"
/*关键定义 左右子树高度差绝对值必须小于2
*/
template <typename T>
struct SimpleAvlTreeNode{
T data;
int depth;
SimpleAvlTreeNode *parent;
SimpleAvlTreeNode *lNode;
SimpleAvlTreeNode *rNode;
SimpleAvlTreeNode<T>(T data, int depth, SimpleAvlTreeNode* parent, SimpleAvlTreeNode* lNode, SimpleAvlTreeNode* rNode) :data(data), depth(depth), parent(parent), lNode(lNode), rNode(rNode) {}
};
template <typename T>
class SimpleAvlTree{
protected:
SimpleAvlTreeNode<T> *root = nullptr;
public:
//检查深度限制
bool checkDepthLimit(SimpleAvlTreeNode<T>* currentNode);
//左旋函数 目的:提升右子节点
SimpleAvlTreeNode<T>* lRotate(SimpleAvlTreeNode<T> *currentNode);
//右旋函数 目的:提升左子节点
SimpleAvlTreeNode<T>* rRotate(SimpleAvlTreeNode<T> *currentNode);
//更新深度信息
SimpleAvlTreeNode<T>* updateDepth(SimpleAvlTreeNode<T> *currentNode);
//增加节点
void addNode(T data);
//删除节点
void removeNode(T data);
void removeNode(SimpleAvlTreeNode<T>* currentNode);
//获取根节点
SimpleAvlTreeNode<T> *getRoot(){ return root; }
//清除内存占用
void clear(SimpleAvlTreeNode<T> *n);
//获取特定节点
SimpleAvlTreeNode<T>* getNode(T data);
SimpleAvlTree(){}
~SimpleAvlTree(){ clear(root); }
};
//清空占用的空间
template <typename T>
void SimpleAvlTree<T>::clear(SimpleAvlTreeNode<T> *n){
if(n->lNode != nullptr)clear(n->lNode);
if(n->rNode != nullptr)clear(n->rNode);
delete n;
}
//检查深度限制
template <typename T>
bool SimpleAvlTree<T>::checkDepthLimit(SimpleAvlTreeNode<T>* currentNode) {
int lNodeDepth = currentNode->lNode == nullptr ? 0 : currentNode->lNode->depth;
int rNodeDepth = currentNode->rNode == nullptr ? 0 : currentNode->rNode->depth;
int depthOffset = lNodeDepth - rNodeDepth;
if (depthOffset > 1 || depthOffset < -1)return false;
else {
//递归检查子节点
bool result = true;
if (currentNode->lNode != nullptr) {
//检查大小限制
if (currentNode->lNode->data >= currentNode->data)return false;
result = checkDepthLimit(currentNode->lNode);
}
if (result) {
if (currentNode->rNode != nullptr) {
//检查大小限制
if (currentNode->rNode->data <= currentNode->data)return false;
result = checkDepthLimit(currentNode->rNode);
}
return result;
}else return false;
}
}
//右旋函数 目的:提升左子节点
//旋转过后 旋转点的原左节点的左节点深度不变,旋转点的新左节点深度不变,旋转点的深度需要改变,并继续更新
template <typename T>
SimpleAvlTreeNode<T>* SimpleAvlTree<T>::rRotate(SimpleAvlTreeNode<T> *currentNode){
//std::cout << "右旋" << std::endl;
//保留旋转点的左节点
SimpleAvlTreeNode<T> *lNode = currentNode->lNode;
//当旋转点的左节点的左节点非空,提升左子节点 还要求左节点的右节点为空或者其两个子节点均为空
if (lNode->lNode != nullptr) {
if (lNode->rNode == nullptr || (lNode->rNode->lNode == nullptr && lNode->rNode->rNode == nullptr)) {
//将旋转点的左节点的右节点转为旋转点的左节点
currentNode->lNode = lNode->rNode;
if (lNode->rNode != nullptr)lNode->rNode->parent = currentNode;
//将旋转点的左节点提升到旋转点所在位置
lNode->parent = currentNode->parent;
if (currentNode->parent != nullptr) {
if (currentNode->parent->lNode == currentNode)currentNode->parent->lNode = lNode;
else currentNode->parent->rNode = lNode;
//父节点为空说明为root节点
}
else this->root = lNode;
//旋转点成为旋转点的左节点的新右节点
lNode->rNode = currentNode;
currentNode->parent = lNode;
return updateDepth(currentNode);
}//当旋转点的左节点的左节点非空,且左节点的右节点存在子节点
//推断 该左节点的右节点只有一个子节点,原因,只要插入一个节点就会导致重平衡 使用该节点替代旋转节点
else {
SimpleAvlTreeNode<T>* assistNode = nullptr;
//当该左节点的右节点的左节点不为空 该左节点的右节点的左节点替代旋转节点
if (lNode->rNode->lNode != nullptr) {
assistNode = lNode->rNode->lNode;
lNode->rNode->lNode = nullptr;
//该左节点的右节点成为旋转节点的左子节点
lNode->rNode->parent = currentNode;
currentNode->lNode = lNode->rNode;
lNode->rNode = nullptr;
}//当该左节点的右节点的右节点不为空 该左节点的右节点替代旋转节点
else {
assistNode = lNode->rNode;
lNode->rNode = nullptr;
//该左节点的右节点的右节点成为旋转节点的左子节点
assistNode->rNode->parent = currentNode;//因为后面重新赋值了assistNode->rNode,所以不需要置空
currentNode->lNode = assistNode->rNode;
}
//使用该节点替代旋转节点
assistNode->parent = currentNode->parent;
if (currentNode->parent != nullptr) {
if (currentNode->parent->lNode == currentNode)currentNode->parent->lNode = assistNode;
else currentNode->parent->rNode = assistNode;
}
else this->root = assistNode;
//该左节点和旋转节点分别成为该节点左右节点
lNode->parent = assistNode;
assistNode->lNode = lNode;
currentNode->parent = assistNode;
assistNode->rNode = currentNode;
updateDepth(currentNode->lNode);
updateDepth(currentNode);
updateDepth(lNode);
return updateDepth(assistNode);
}
}//当旋转点的左节点的左节点为空,提升左子节点的右子节点(此时左子节点的右子节点必不为空)
else {
SimpleAvlTreeNode<T>* assistNode = lNode->rNode;
//左子节点的右子节点提升到旋转点所在位置
assistNode->parent = currentNode->parent;
if (currentNode->parent != nullptr) {
if (currentNode->parent->lNode == currentNode)currentNode->parent->lNode = assistNode;
else currentNode->parent->rNode = assistNode;
//父节点为空说明为root节点
}
else this->root = assistNode;
//断开左子节点的右子节点和左子节点的连接 左子节点的右子节点的左子节点成为左子节点的新右子节点,左子节点的右子节点的右子节点成为旋转点的新左子节点
lNode->rNode = assistNode->lNode;
if (lNode->rNode != nullptr)lNode->rNode->parent = lNode;
currentNode->lNode = assistNode->rNode;
if (currentNode->lNode != nullptr)currentNode->lNode->parent = currentNode;
//左子节点成为左子节点的右子节点的新左子节点
assistNode->lNode = lNode;
lNode->parent = assistNode;
//旋转点成为左子节点的右子节点的新右子节点
assistNode->rNode = currentNode;
currentNode->parent = assistNode;
updateDepth(currentNode);
updateDepth(lNode);
return updateDepth(assistNode);
}
}
//左旋函数 目的:提升右子节点
//旋转过后 旋转点的原右节点的右节点深度不变,旋转点的新右节点深度不变,旋转点的深度需要改变,并继续更新
template <typename T>
SimpleAvlTreeNode<T>* SimpleAvlTree<T>::lRotate(SimpleAvlTreeNode<T> *currentNode){
//std::cout << "左旋" << std::endl;
//保留旋转点的右节点
SimpleAvlTreeNode<T> *rNode = currentNode->rNode;
//当旋转点的右节点的右节点非空,提升右子节点 还要求右节点的左节点为空或者其两个子节点均为空
if (rNode->rNode != nullptr) {
if (rNode->lNode == nullptr || (rNode->lNode->lNode == nullptr && rNode->lNode->rNode == nullptr)) {
//将旋转点的右节点的左节点转为旋转点的右节点
currentNode->rNode = rNode->lNode;
if (rNode->lNode != nullptr)rNode->lNode->parent = currentNode;
//将旋转点的右节点提升到旋转点所在位置
rNode->parent = currentNode->parent;
if (currentNode->parent != nullptr) {
if (currentNode->parent->lNode == currentNode)currentNode->parent->lNode = rNode;
else currentNode->parent->rNode = rNode;
//父节点为空说明为root节点
}
else this->root = rNode;
//旋转点成为旋转点的右节点的新左节点
rNode->lNode = currentNode;
currentNode->parent = rNode;
return updateDepth(currentNode);
}//当旋转点的右节点的右节点非空,且右节点的左节点存在子节点
//推断 该右节点的左节点只有一个子节点,原因,只要插入一个节点就会导致重平衡 使用该节点替代旋转节点
else {
SimpleAvlTreeNode<T>* assistNode = nullptr;
//当该右节点的左节点的左节点不为空
if (rNode->lNode->lNode != nullptr) {
//该右节点的左节点替代旋转节点
assistNode = rNode->lNode;
rNode->lNode = nullptr;
//该右节点的左节点的左节点成为旋转节点的右子节点
assistNode->lNode->parent = currentNode;//因为后面重新赋值了assistNode->lNode,所以不需要置空
currentNode->rNode = assistNode->lNode;
}
//当该右节点的左节点的右节点不为空
else {
//该右节点的左节点的右节点替代旋转节点
assistNode = rNode->lNode->rNode;
rNode->lNode->rNode = nullptr;
//该右节点的左节点成为旋转节点的右子节点
rNode->lNode->parent = currentNode;
currentNode->rNode = rNode->lNode;
rNode->lNode = nullptr;
}
//使用该节点替代旋转节点
assistNode->parent = currentNode->parent;
if (currentNode->parent != nullptr) {
if (currentNode->parent->lNode == currentNode)currentNode->parent->lNode = assistNode;
else currentNode->parent->rNode = assistNode;
}
else this->root = assistNode;
//该左节点和旋转节点分别成为该节点左右节点
rNode->parent = assistNode;
assistNode->rNode = rNode;
currentNode->parent = assistNode;
assistNode->lNode = currentNode;
updateDepth(currentNode->rNode);
updateDepth(currentNode);
updateDepth(rNode);
return updateDepth(assistNode);
}
}//当旋转点的右节点的右节点为空,提升右子节点的左子节点(此时右子节点的左子节点必不为空)
else {
SimpleAvlTreeNode<T>* assistNode = rNode->lNode;
//右子节点的左子节点提升到旋转点所在位置
assistNode->parent = currentNode->parent;
if (currentNode->parent != nullptr) {
if (currentNode->parent->lNode == currentNode)currentNode->parent->lNode = assistNode;
else currentNode->parent->rNode = assistNode;
//父节点为空说明为root节点
}
else this->root = assistNode;
//断开右子节点的左子节点和右子节点的连接 右子节点的左子节点的左子节点成为旋转点的新右子节点,右子节点的左子节点的右子节点成为右子节点的新左子节点
currentNode->rNode = assistNode->lNode;
if (currentNode->rNode != nullptr)currentNode->rNode->parent = currentNode;
rNode->lNode = assistNode->rNode;
if (rNode->lNode != nullptr)rNode->lNode->parent = rNode;
//右子节点成为右子节点的左子节点的新右子节点
rNode->parent = assistNode;
assistNode->rNode = rNode;
//旋转点成为右子节点的左子节点的新左子节点
currentNode->parent = assistNode;
assistNode->lNode = currentNode;
updateDepth(currentNode);
updateDepth(rNode);
return updateDepth(assistNode);
}
}
//更新深度信息
template <typename T>
SimpleAvlTreeNode<T>* SimpleAvlTree<T>::updateDepth(SimpleAvlTreeNode<T> *currentNode){
int lNodeDepth = currentNode->lNode == nullptr ? 0 : currentNode->lNode->depth;
int rNodeDepth = currentNode->rNode == nullptr ? 0 : currentNode->rNode->depth;
int maxDepth = lNodeDepth >= rNodeDepth ? lNodeDepth : rNodeDepth;
int depthOffset = lNodeDepth - rNodeDepth;
//左边的深度高出1以上,左旋
if(depthOffset > 1){
return rRotate(currentNode);
}
else if(depthOffset < -1){
return lRotate(currentNode);
//终止条件,当前的depth数据正确并不合理,可能当前节点的depth数据正确但上层的depth数据不正确
//改为一直更新到根节点
}
else {
currentNode->depth = maxDepth + 1;
return currentNode->parent;
}
}
//删除节点
//删除非叶子节点,该节点既有左孩子,又有右孩子。操作:该节点的值替换为该节点的前驱节点(或者后继节点),然后删除前驱节点(或者后继节点)
template <typename T>
void SimpleAvlTree<T>::removeNode(SimpleAvlTreeNode<T>* currentNode) {
if (currentNode != nullptr) {
//保留父节点
SimpleAvlTreeNode<T>* assistNode = currentNode->parent;
SimpleAvlTreeNode<T>* nextNode = nullptr;
if (currentNode->lNode != nullptr && currentNode->rNode != nullptr) {
//找前驱节点
SimpleAvlTreeNode<T>* frontDriveNode = currentNode->lNode;
while (frontDriveNode->rNode != nullptr) {
frontDriveNode = frontDriveNode->rNode;
}
//保留currentNode但更新数据信息
currentNode->data = frontDriveNode->data;
removeNode(frontDriveNode);
return;//跳过删除当前节点
}
else if (currentNode->lNode != nullptr && currentNode->rNode == nullptr) {
//如果父节点为空则不需要更新父节点信息 但需要更新root
if (assistNode != nullptr) {
//连接需要双向更新
if (assistNode->lNode == currentNode)assistNode->lNode = currentNode->lNode;
else assistNode->rNode = currentNode->lNode;
currentNode->lNode->parent = assistNode;
//更新父节点深度信息
nextNode = updateDepth(assistNode);
while (nextNode != nullptr) {
nextNode = updateDepth(nextNode);
}
}
else {
//连接需要双向更新
this->root = currentNode->lNode;
currentNode->lNode->parent = nullptr;
}
}//如果某个节点为空,则只要用非空子节点代替被删除的节点
else if (currentNode->lNode == nullptr && currentNode->rNode != nullptr) {
//如果父节点为空则不需要更新父节点信息 但需要更新root
if (assistNode != nullptr) {
//连接需要双向更新
if (assistNode->lNode == currentNode)assistNode->lNode = currentNode->rNode;
else assistNode->rNode = currentNode->rNode;
currentNode->rNode->parent = assistNode;
//更新父节点深度信息
nextNode = updateDepth(assistNode);
while (nextNode != nullptr) {
nextNode = updateDepth(nextNode);
}
}
else {
//连接需要双向更新
this->root = currentNode->rNode;
currentNode ->rNode->parent = nullptr;
}
}//如果两个子节点均空,说明为叶子节点,直接删除后更新深度信息
else {
//如果父节点为空则不需要更新父节点信息 但需要更新root
if (assistNode != nullptr) {
if (assistNode->lNode == currentNode)assistNode->lNode = nullptr;
else assistNode->rNode = nullptr;
//更新父节点深度信息
nextNode = updateDepth(assistNode);
while (nextNode != nullptr) {
nextNode = updateDepth(nextNode);
}
}
else this->root = nullptr;
}
//删除当前节点
delete currentNode;
}
}
template <typename T>
void SimpleAvlTree<T>::removeNode(T data) {
if (this->root == nullptr)return ;
else {
SimpleAvlTreeNode<T>* node = getNode(data);
if (node != nullptr)removeNode(node);
}
}
//获取特定节点
template <typename T>
SimpleAvlTreeNode<T>* SimpleAvlTree<T>::getNode(T data) {
if (this->root == nullptr)return nullptr;
else {
SimpleAvlTreeNode<T>* currentNode = this->root;
//遍历AVL树,找到匹配的节点
while (true) {
if (data == currentNode->data) {
return currentNode;
}
else if (data > currentNode->data) {
if (currentNode->rNode != nullptr)currentNode = currentNode->rNode;
else return nullptr;
}
else {
if (currentNode->lNode != nullptr)currentNode = currentNode->lNode;
else return nullptr;
}
}
}
}
//增加节点
template <typename T>
void SimpleAvlTree<T>::addNode(T data){
if(this->root == nullptr){//默认单个节点深度为0
this->root = new SimpleAvlTreeNode<T>(data, 1, nullptr, nullptr, nullptr);
}else {
SimpleAvlTreeNode<T> *currentNode = this->root;
SimpleAvlTreeNode<T>* nextNode = nullptr;
while(true){
//比较该数据与当前节点的数值
if(data >= currentNode->data){
//如果大于等于且当前节点右值为空,插入
if(currentNode->rNode == nullptr){
currentNode->rNode = new SimpleAvlTreeNode<T>(data, 1, currentNode, nullptr, nullptr);
nextNode = updateDepth(currentNode);
while (nextNode != nullptr) {
nextNode = updateDepth(nextNode);
}
return ;
}else currentNode = currentNode->rNode;//如果大于等于但当前节点右值非空,继续比较
}else {
//如果大于等于且当前节点左值为空,插入
if(currentNode->lNode == nullptr){
currentNode->lNode = new SimpleAvlTreeNode<T>(data, 1, currentNode, nullptr, nullptr);
nextNode = updateDepth(currentNode);
while (nextNode != nullptr) {
nextNode = updateDepth(nextNode);
}
return ;
//如果大于等于但当前节点左值非空,继续比较
}else currentNode = currentNode->lNode;
}
}
}
}
class SimpleIntAvlTree : public SimpleAvlTree<int>{
public:
void iteratorTreeString(SimpleAvlTreeNode<int> *currentNode);
char *toString();
char *depthToString();
SimpleIntAvlTree(){}
~SimpleIntAvlTree(){}
};
void SimpleIntAvlTree::iteratorTreeString(SimpleAvlTreeNode<int> *currentNode){
if(currentNode->lNode != nullptr)iteratorTreeString(currentNode->lNode);
std::cout << currentNode->data;
if(currentNode->rNode != nullptr)iteratorTreeString(currentNode->rNode);
}
char *SimpleIntAvlTree::toString(){
if (root == nullptr) {
SimpleString str = SimpleString("空树");
return str.getData();
}
SimpleQueue<SimpleAvlTreeNode<int> *> *ss = new SimpleQueue<SimpleAvlTreeNode<int> *>();
SimpleQueue<SimpleAvlTreeNode<int> *> *ssNext = new SimpleQueue<SimpleAvlTreeNode<int> *>();
SimpleQueue<SimpleAvlTreeNode<int> *> *temp = nullptr;
SimpleAvlTreeNode<int> *n = nullptr;
ss->push(root);
SimpleStringBuilder strBuilder;
SimpleString layerInsideGap = SimpleString(" ");
SimpleString layerGap = SimpleString("\n");
while(true){
while(!ss->isEmpty()){
n = ss->pop_back();
if(n->lNode != nullptr)ssNext->push(n->lNode);
if(n->rNode != nullptr)ssNext->push(n->rNode);
SimpleString data = SimpleString((long)n->data);
strBuilder.append(layerInsideGap);
strBuilder.append(data);
}
if(!ssNext->isEmpty()){
temp = ss;
ss = ssNext;
ssNext = temp;
strBuilder.append(layerGap);
}else break;
}
int length = strBuilder.getLength();
char *s = new char[length + 1];
memcpy(s, strBuilder.getData(), length);
s[length] = 0;
//释放空间
delete ss;
delete ssNext;
return s;
}
char *SimpleIntAvlTree::depthToString(){
if (root == nullptr) {
SimpleString str = SimpleString("空树");
return str.getData();
}
SimpleQueue<SimpleAvlTreeNode<int> *> *ss = new SimpleQueue<SimpleAvlTreeNode<int> *>();
SimpleQueue<SimpleAvlTreeNode<int> *> *ssNext = new SimpleQueue<SimpleAvlTreeNode<int> *>();
SimpleQueue<SimpleAvlTreeNode<int> *> *temp = nullptr;
SimpleAvlTreeNode<int> *n = nullptr;
ss->push(root);
SimpleStringBuilder strBuilder;
SimpleString layerInsideGap = SimpleString(" ");
SimpleString layerGap = SimpleString("\n");
while(true){
while(!ss->isEmpty()){
n = ss->pop_back();
if(n->lNode != nullptr)ssNext->push(n->lNode);
if(n->rNode != nullptr)ssNext->push(n->rNode);
SimpleString data = SimpleString((long)n->depth);
strBuilder.append(layerInsideGap);
strBuilder.append(data);
}
if(!ssNext->isEmpty()){
temp = ss;
ss = ssNext;
ssNext = temp;
strBuilder.append(layerGap);
}else break;
}
int length = strBuilder.getLength();
char *s = new char[length + 1];
memcpy(s, strBuilder.getData(), length);
s[length] = 0;
//释放空间
delete ss;
delete ssNext;
return s;
}
#endif // SIMPLEAVLTREE_H