【问题标题】:code=139 Error[Segmentation Fault] AVL Tree insertion代码=139 错误[分段错误] AVL 树插入
【发布时间】:2020-08-07 11:36:47
【问题描述】:

我有 add_node 函数,它正在向树中添加节点,但是当我倾斜说正确时,它会给出分段错误。

template<class T>
class avl{
   private:
      Node<T>* root;
    public:
    //CONSTRUCTOR
       avl(){
           root=nullptr;
       }
//HEIGHT FUNCTION
    int get_height(){
       return get_height(this->root);   
    }
    int get_height(Node<T>* node){
        int l_height,r_height;
        if(node==nullptr){return -1;}
        else{
        l_height=get_height(node->m_left);
        r_height=get_height(node->m_right);

        if(l_height>=r_height){return l_height+1;}
        else{return r_height+1;}
        }
    }
    //BALANCE_FACTOR
    int balance_factor(Node<T>* node){
        return get_height(node->m_left)- get_height(node->m_right);
    }
    Node<T>* ll_rotate(Node<T>* &node){
        Node<T>* temp=nullptr;
        temp=node->m_right;
        node->m_right=temp->m_left;
        temp->m_left=node;
        return temp;
   }
 Node<T>* rr_rotate(Node<T>* &node){
        Node<T>* temp=nullptr;
        temp=node->m_left;
        node->m_left=temp->m_right;
        temp->m_right=node;
        return temp;
    }
    Node<T>* rl_rotate(Node<T>* &node){
        node->m_right=rr_rotate(node->m_right);
        return ll_rotate(node);
    }
        Node<T>* lr_rotate(Node<T>* &node){
        node->m_left=ll_rotate(node->m_left);
        return rr_rotate(node);
    }

//Rebalance Tree
    Node<T>* rebalance(Node<T>* &node){
        int bf= balance_factor(node);
        
        if(bf>1){
            if(balance_factor(node->m_left)>1){
               return rr_rotate(node);
            }else{
               return lr_rotate(node);
            }
        }else if(bf<-1){
            if(balance_factor(node->m_right)<-1){
              return  ll_rotate(node);
            }else{
               return rl_rotate(node);
            }
        }
        return node;
    }
   void add_node(T data){
     add_node(data,this->root);
           }
   Node<T>* add_node(T data,Node<T>* node){
            if(node==nullptr){
                Node<T>* new_node= new Node<T>(data);
                 return new_node;
            }
            if(data>node->m_data){
                node->m_right=add_node(data,node->m_right);
            } else if(data<node->m_data){
                node->m_left=add_node(data,node->m_left);
            }
        /*    int bf= balance_factor(node);
            //ll case
            if(bf>1 && data<node->m_left->m_data){
                return rr_rotate(node);
            }//rr case
            if(bf<-1 && data>node->m_right->m_data){
                return ll_rotate(node);
            }//lr case
            if(bf>1 && data>node->m_left->m_data){
                  return lr_rotate(node);
            }//rl case
             if(bf<-1 && data<node->m_right->m_data){
                  return rl_rotate(node);
            }*/
            return rebalance(node);
    }

节点.h

template<class T>
class Node{
  private:
  public:
     T m_data;
     Node<T>* m_left;
     Node<T>* m_right;
     
     Node(T data){
        m_data =data;
        m_left=nullptr;
        m_right=nullptr;
     }
};

main.cpp

#include<iostream>
#include"avl.h"

using namespace std;

int main(){
  avl<int> a1;
  a1.add_node(20);
  a1.add_node(25);
  a1.add_node(30);  //Error is happening at this point

}

当我添加 30 时发生崩溃。那时,我有一棵树

20
 \
  25
   \
    30

add_node 在 20 节点上调用 rebalance。平衡因子为 -2,节点 25 的平衡因子为 -1,这意味着它在 20 节点上调用 rr_rotate(node)。这会立即调用第 25 个节点上的 ll_rotate(node->m_right)。该函数有这两行

temp=node->m_left; 节点->m_left=temp->m_right;

由于节点是25个节点所以node->m_left为null,所以temp为null,所以temp->m_right是crash。

我怎么会遇到这个问题?

【问题讨论】:

  • 请了解如何使用调试器来捕捉崩溃,并在代码中定位崩溃发生的时间和位置。它还允许您在崩溃时检查变量及其值。
  • 我已经使用调试器知道了这个事实,但是我对 node->m_left==nullptr 感到困惑,所以我如何将临时节点的权利分配给它!
  • 如果你能读懂这个问题,你就会知道它不是关于分段错误,而是这个错误发生的方式! @Someprogrammerdude
  • 然后使用调试器逐步逐句执行代码。
  • 这样做是不是我已经知道问题出在哪里了,但我不知道解决方案,所以我在这里发布了!

标签: c++ binary-tree binary-search-tree avl-tree


【解决方案1】:

问题在于对节点的重新平衡检查。在重新平衡树功能中,当我检查父母的平衡因子然后检查父母的左或右孩子时,使用的值是错误的。它不应该是 -1 或 1 它应该是 0。因为我们正在执行旋转的节点的子节点不必具有大于 1 或小于 -1 的平衡因子。但它总是大于 0。 因此,如果在左重父的情况下它大于 0,那么我们应该执行 rr_rotation[For left-left case] 并且类似地对右重子树执行 ll_rotation。 以下是工作函数:

Node<T>* rebalance(Node<T>* &node){
       int bf= balance_factor(node);
       if(bf>1){
           if(balance_factor(node->m_left)>0){
               return rr_rotate(node);
           }else{return lr_rotate(node);}
       }
       if(bf<-1){
           if(balance_factor(node->m_right)>0){
               return rl_rotate(node);
           }else{return ll_rotate(node);}
       }
       return node;
   }

【讨论】:

    猜你喜欢
    • 2019-10-18
    • 2017-01-20
    • 1970-01-01
    • 2014-03-17
    • 2021-04-16
    • 1970-01-01
    • 2016-09-13
    • 2019-08-11
    • 2021-04-08
    相关资源
    最近更新 更多