【OJ题解-2】无栈实现AVL树的插入删除

一、试题题面

实现AVL的插入删除操作,要求对于AVL执行插入删除操作时不使用递归操作(使用数组模拟栈),在结点的定义中不使用指向父结点的指针。操作从空的AVL树开始。

【输入输出约定】

输入:

首先是一个整数N,表示有N次操作。

接下来的N行中,每一行可能是如下之一: 1.1 Data 表示将Data插入到AVL树中, 然后按照格式要求输出插入后的AVL树  2. 2 Data 表示将Data从AVL树中删除,然后按照格式要求输出删除后的AVL树(本题中AVL树按set处理,如果插入树中已有元素,则不插入)。

输出:

 a)空树输出空串
 b)对于非空的AVL树root,输出为  '(' 左子树的输出串 root->data root->balanceFactor 右子树的输出串 ')'

【测试数据样例】

输入

6 
1 114
1 514 
1 1919
1 810
1 233
2 514

输出

(114,0)
(114,-1(514,0))
((114,0)514,0(1919,0))
((114,0)514,-1((810,0)1919,1))
((114,-1(233,0))514,0((810,0)1919,1))
((114,0)233,-1((810,0)1919,1))

样例解释

508dbd063cb84f268d3d605d51fc4c8a.png 

二、试题理解

AVL树是基础数据结构中避免树的高度增长过快,降低二叉树的性能规定的一类二叉树。定义节点左子树与右子树的高度差为该节点的平衡因子。平衡二叉树可定义为或是一棵空树,或是具有以下两个性质的二叉树:左子树和右子树都是平衡二叉树且左子树和右子树的高度差的绝对值不超过1。

在AVL树的结点定义中不使用指向父结点的parent指针、不在插入删除操作中使用递归可以有效减少其存储空间的占用(由于评测原因,本题解提供的代码并没有及时释放调用的存储空间资源以保证本文提供的代码能正常编译运行并通过评测)。虽然这是OJ试题的要求,但是这种思想也是值得学习的——在既定的ADT的实现上做出一些小的改进以获得更良好的效果。在如此实现的过程中,不仅可以更加熟悉AVL树的基本操作,更可以对递归与栈有更深入的思考。个人认为这样的试题设置在某种意义上比做一道单纯为了考察栈的操作而设置的、乃至于即使不使用栈也可以实现但是强调一定需要使用栈的问题并写一篇看起来洋洋洒洒的实验报告更有帮助。

三、实现细节

AVL树的基本操作属于基础数据结构的理论部分,不再赘述。本实现中的LR平衡旋转(先左后右双旋转)/RL平衡旋转(先右后左双旋转)均可以通过右单旋转和左单旋转的函数调用实现,在源代码中给出了两个函数不借助于其他函数的实现。

实验中使用了用数组模拟栈的形式记录了因为插入删除操作平衡因子需要改变以及可能需要旋转操作的结点,使用循环遍历的方式更新平衡因子及此时可能需要的旋转操作。

四、完整实现代码

#include<iostream>
#define Past_Dream FW
using namespace std;
struct Node{
    int data;
    int height;
    int balance_factor;
    Node* left;
    Node* right;
    Node(int data):data(data),height(1),balance_factor(0),left(NULL),right(NULL){}
};
class AVLTree{
public:    
    Node* root;
    AVLTree():root(NULL){}
    void RR_Balanced_Rotation(Node* &node,Node* &parent);
    void LL_Balanced_Rotation(Node* &node, Node* &parent);
    void RL_Balanced_Rotation(Node* &node, Node* &parent);
    void LR_Balanced_Rotation(Node* &node, Node* &parent);
    void Insert(int data);
    void Delete(int data);
    void Inorder_Traversal(Node* node);
    void PrintTree(Node* node);
    int Height(Node* node);
    int GetBalanceFactor(Node* node);
    int Max(int a,int b);
};
int AVLTree::Height(Node* node){
    if(node==NULL) return 0;
    return node->height;
}
int AVLTree::GetBalanceFactor(Node* node){
    if(node==NULL) return 0;
    return Height(node->left)-Height(node->right);
}
int AVLTree::Max(int a, int b){
    return a>b?a:b;
}
void AVLTree::LL_Balanced_Rotation(Node* &node, Node* &parent){
    Node* temp = node->left;
    node->left = temp->right;
    temp->right = node;
    if(parent!=NULL){
        if(parent->left==node) parent->left = temp;
        else parent->right = temp;
    }else{
        root = temp;
    }
    node = temp;
    node->left->height = Max(Height(node->left->left), Height(node->left->right))+1;
    node->left->balance_factor = GetBalanceFactor(node->left);
    node->right->height = Max(Height(node->right->left), Height(node->right->right))+1;
    node->right->balance_factor = GetBalanceFactor(node->right);
    node->height = Max(Height(node->left), Height(node->right))+1;
    node->balance_factor = GetBalanceFactor(node);
}
void AVLTree::RR_Balanced_Rotation(Node* &node, Node* &parent){
    Node* temp = node->right;
    node->right = temp->left;
    temp->left = node;
    if(parent!=NULL){
        if(parent->left==node) parent->left = temp;
        else parent->right = temp;
    }else{
        root = temp;
    }
    node = temp;
    node->left->height = Max(Height(node->left->left), Height(node->left->right))+1;
    node->left->balance_factor = GetBalanceFactor(node->left);
    node->right->height = Max(Height(node->right->left), Height(node->right->right))+1;
    node->right->balance_factor = GetBalanceFactor(node->right);
    node->height = Max(Height(node->left), Height(node->right))+1;
    node->balance_factor = GetBalanceFactor(node);
}
void AVLTree::RL_Balanced_Rotation(Node* &node, Node* &parent){
    Node* temp = node->right->left;
    node->right->left = temp->right;
    temp->right = node->right;
    node->right = temp->left;
    temp->left = node;
    if(parent!=NULL){
        if(parent->left==node) parent->left = temp;
        else parent->right = temp;
    }else{
        root = temp;
    }
    node = temp;
    node->left->height = Max(Height(node->left->left), Height(node->left->right))+1;
    node->left->balance_factor = GetBalanceFactor(node->left);
    node->right->height = Max(Height(node->right->left), Height(node->right->right))+1;
    node->right->balance_factor = GetBalanceFactor(node->right);
    node->height = Max(Height(node->left), Height(node->right))+1;
    node->balance_factor = GetBalanceFactor(node);
}
void AVLTree::LR_Balanced_Rotation(Node* &node, Node* &parent){
    Node* temp = node->left->right;
    node->left->right = temp->left;
    temp->left = node->left;
    node->left = temp->right;
    temp->right = node;
    if(parent!=NULL){
        if(parent->left==node) parent->left = temp;
        else parent->right = temp;
    }else{
        root = temp;
    }
    node = temp;
    node->left->height = Max(Height(node->left->left), Height(node->left->right))+1;
    node->left->balance_factor = GetBalanceFactor(node->left);
    node->right->height = Max(Height(node->right->left), Height(node->right->right))+1;
    node->right->balance_factor = GetBalanceFactor(node->right);
    node->height = Max(Height(node->left), Height(node->right))+1;
    node->balance_factor = GetBalanceFactor(node);
}
void AVLTree::Insert(int data){
    Node* new_node = new Node(data);
    if(root==NULL){
        root = new_node;
        return;
    }
    Node* current = root , tempnode(0) , tempnoderight(0) , tempnodeleft(0);
    Node* ancestors[current->height + 5];
    int index = 1;
    ancestors[0] = NULL;
    while(current!=NULL){
        ancestors[index++] = current;
        if(data<current->data){
            current = current->left;
        }else if(data>current->data){
            current = current->right;
        }else{
            return;
        }
    }
    if(data<ancestors[index-1]->data){
        ancestors[index-1]->left = new_node;
    }else{
        ancestors[index-1]->right = new_node;
    }
    for(int i=index-1;i >= 1;i--){
        ancestors[i]->height = Max(Height(ancestors[i]->left), Height(ancestors[i]->right))+1;
        ancestors[i]->balance_factor = GetBalanceFactor(ancestors[i]);
        if(ancestors[i]->balance_factor > 1){
            if(ancestors[i]->left->balance_factor >= 0){
                LL_Balanced_Rotation(ancestors[i], ancestors[i-1]);
            }else{
                LR_Balanced_Rotation(ancestors[i], ancestors[i-1]);
            }
        }else if(ancestors[i]->balance_factor < -1){
            if(ancestors[i]->right->balance_factor <= 0){
                RR_Balanced_Rotation(ancestors[i], ancestors[i-1]);
            }else{
                RL_Balanced_Rotation(ancestors[i], ancestors[i-1]);
            }
        }
    }
}
void AVLTree::Delete(int data){
    Node* current = root , tempnode(0) , tempnoderight(0) , tempnodeleft(0);
    Node* ancestors[current->height + 5];
    int index = 1;
    ancestors[0] = NULL;
    while(current!=NULL){
        ancestors[index++] = current;
        if(data < current->data){
            current = current->left;
        }else if(data > current->data){
            current = current->right;
        }else{
            break;
        }
    }
    if(current==NULL) return;
    if(current->left==NULL && current->right==NULL){
        if(ancestors[index-2]->left==current){
            ancestors[index-2]->left = NULL;
        }else{
            ancestors[index-2]->right = NULL;
        }
    }else if(current->left==NULL){
        if(ancestors[index-2]->left==current){
            ancestors[index-2]->left = current->right;
        }else{
            ancestors[index-2]->right = current->right;
        }
    }else if(current->right==NULL){
        if(ancestors[index-2]->left==current){
            ancestors[index-2]->left = current->left;
        }else{
            ancestors[index-2]->right = current->left;
        }
    }else{
        Node* temp = current->left;
        ancestors[index++] = temp;
        Node* temp2 = current;
        while(temp->right!=NULL){
            temp2 = temp;
            temp = temp2->right;
            ancestors[index++] = temp;
        }
        current->data = temp->data;
        if(temp->left==NULL && temp2 != current){
            temp2->right = NULL;
        }
        else if(temp2 == current){
            temp2->left = temp->left;
        }
        else{
            temp2->right = temp->left;
        }
    }
    for(int i=index-1;i >= 1;i--){
        ancestors[i]->height = Max(Height(ancestors[i]->left), Height(ancestors[i]->right))+1;
        ancestors[i]->balance_factor = GetBalanceFactor(ancestors[i]);
        if(ancestors[i]->balance_factor > 1){
            if(ancestors[i]->left->balance_factor >= 0){
                LL_Balanced_Rotation(ancestors[i], ancestors[i-1]);
            }else{
                LR_Balanced_Rotation(ancestors[i], ancestors[i-1]);
            }
        }else if(ancestors[i]->balance_factor < -1){
            if(ancestors[i]->right->balance_factor <= 0){
                RR_Balanced_Rotation(ancestors[i], ancestors[i-1]);
            }else{
                RL_Balanced_Rotation(ancestors[i], ancestors[i-1]);
            }
        }
    }
}
void AVLTree::Inorder_Traversal(Node* node){
    if(node==NULL) return;
    Inorder_Traversal(node->left);
    cout << node->data << " " ;
    Inorder_Traversal(node->right);
}
void AVLTree::PrintTree(Node* node){
    if(node==NULL) return;
    cout << "(" ;
    PrintTree(node->left);
    cout << node->data << "," << node->balance_factor;
    PrintTree(node->right);
    cout << ")" ;
}
int main(){
    AVLTree avl;
    int n , tempdata , tempop;
    cin >> n;
    for(int i = 0 ; i < n ; i ++){
        cin >> tempop >> tempdata;
        switch (tempop){
            case 1:
                avl.Insert(tempdata);
                avl.PrintTree(avl.root);
                cout << endl;
                break;
            case 2:
                avl.Delete(tempdata);
                avl.PrintTree(avl.root);
                cout << endl;
                break;
            default:
                cout << "Invalid Operation" << endl;
                break;
        }
    }
    return 0;
}

以上代码通过了OJ评测,但是并不保证正确。由于笔者本身是小飞舞,文章中必然会存在些许的错误与不足,衷心恳请您能够批评和指正。


今天是10月1日,祝福我们伟大的祖国繁荣昌盛、国泰民安!

去思考,去尝试,去突破,去成长

衷心感谢您的阅读,我们下次再见!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值