【问题标题】:nullptr = Node is not assigning correctlynullptr = 节点分配不正确
【发布时间】:2019-10-13 07:52:01
【问题描述】:

请不要太深入研究我,我还在稳步学习,在尝试构建 AVL 树时遇到了问题。在插入时遍历树时,我会一直走到一个 nullptr,创建一个新节点,然后将该 ptr 分配给 nullptr。但是,该值永远不会被接受。有人可以找到错误并向我解释吗?太棒了!

#ifndef AVLTree_hpp
#define AVLTree_hpp

#include <stdio.h>
#include <stack>
template<typename T>
class AVLTree{
private:
    struct Node{
        T val;
        Node* left;
        Node* right;
        int height;

        Node(T V)
        :left{nullptr},right{nullptr}
        {
            val = V;
        }
        ~Node(){

        }
    };
    Node* head;
    void rightRotate(Node*& node);
    void leftRotate(Node*& node);
    void leftRight(Node*& node);
    void rightLeft(Node*& node);


public:
    AVLTree();
    ~AVLTree();
    AVLTree(const AVLTree &c);
    AVLTree(AVLTree &&c);
    AVLTree &operator=(const AVLTree &c);
    AVLTree &operator=(AVLTree &&c);
    void add(T value);
    int getHeight(Node* n);
};

template <typename T>
AVLTree<T>::AVLTree()
    :head{nullptr}{
}
template <typename T>
AVLTree<T>::~AVLTree(){

}

template <typename T>
void AVLTree<T>::rightRotate(Node*& node){
    Node* temp = node;
    node = node->left;
    Node* leftLL = node->right;
    temp->left = leftLL;
    node->right = temp;
}
template <typename T>
void AVLTree<T>::leftRotate(Node*& node) {
    Node* temp = node;
    node = node->right;
    Node* yL = node->left;
    temp->right = yL;
    node->left = temp;
}
//left right condition
template <typename T>
void AVLTree<T>::leftRight(Node*& node) {
    leftRotate(node->left);
    rightRotate(node);
}

//right left condition
template <typename T>
void AVLTree<T>::rightLeft(Node*& node){
    rightRotate(node->right);
    leftRotate(node);
}
template <typename T>
void AVLTree<T>::add(T value){
    if(head==nullptr){
        head = new Node(value);
        return;
    }
    std::stack<Node*> st;
    Node* it = head;
    while(it!=nullptr){
        st.push(it);
        if(value <= it->val){
            it = it->left;
        }else{
            it=it->right;
        }
    }
//here is where the it is not assigned to the new node pointer. 
//I have tested it and the node is created, "it" just does not hold the value at any point.
    it = new Node(value);
    int count = 0;
    while(!st.empty()){
        int balance = getHeight(st.top()->left) - getHeight(st.top()->right);
        if(balance > 1){
            if(st.top()->left!= nullptr&&st.top()->left!=nullptr){
                leftRotate(st.top());
            }else{
                leftRight(st.top());
            }
        }else if(balance<-1){
            if(st.top()->right!=nullptr&&st.top()->right!=nullptr){
                rightRotate(st.top());
            }else{
                rightLeft(st.top());
            }
        }
        st.pop();
        if(++count==4){
            break;
        }
    }
}
template <typename T>
int AVLTree<T>::getHeight(Node* n){
    int max =0;
    if(n!=nullptr){
        max = std::max(getHeight(n->left),getHeight(n->right))+1;
    }
    return max;
}


#endif /* AVLTree_hpp */


【问题讨论】:

  • “该值永远不会被接受”是什么意思 - 在运行程序时如何体现(异常、段错误、无效状态等)?
  • 修改堆栈st 中的元素对您从中复制它的树节点没有影响。指针没有什么特别之处。

标签: c++ pointers avl-tree


【解决方案1】:

It 是指针的副本,更新它对原始指针没有影响。你需要这样做:

Node* it = head;
bool left = true;
while(it!=nullptr){
    st.push(it);
    left = value <= it->val;
    if(left){
        it = it->left;
    }else{
        it=it->right;
    }
}
it = new Node(value);
if (left){
    stack.top()->left = it;
} else {
    stack.top()->right = it;
}

【讨论】:

    【解决方案2】:

    考虑一下您的代码的这个简化版本:

    #include <iostream>
    
    struct Linked {
        Linked* next;
    };
    
    int main(int argc, char** argv) {
        Linked l0 {nullptr};
    
        // Case 1: Does not work
        std::cout << "case 1" << std::endl;
        Linked* node = l0.next;
        node = new Linked {nullptr};
        std::cout << "node=" << std::hex << node << std::endl;
        std::cout << "l0.next=" << std::hex << l0.next << std::endl;
        free(node);
        std::cout << std::endl;
    
        // Case 2: Works
        std::cout << "case 2" << std::endl;
        l0.next = new Linked {nullptr};
        std::cout << "l0.next=" << std::hex << l0.next << std::endl;
        free(l0.next);
        l0.next = nullptr;
        std::cout << std::endl;
    
        // Case 3: Works
        std::cout << "case 3" << std::endl;
        Linked** nodeP = &(l0.next);
        *nodeP = new Linked {nullptr};
        std::cout << "*nodeP=" << std::hex << *nodeP << std::endl;
        std::cout << "l0.next=" << std::hex << l0.next << std::endl;
        free(l0.next);
        l0.next = nullptr;
    }
    

    哪些输出:

    $ ./main 
    case 1
    node=0x7fba0d400620
    l0.next=0x0
    
    case 2
    l0.next=0x7fba0d400620
    
    case 3
    *nodeP=0x7fba0d400620
    l0.next=0x7fba0d400620
    
    • 案例1:不起作用,因为新的Node 被分配给左/右子指针的副本(即不是来自父节点的实际子节点)
    • 案例 2:按预期工作,因为新节点直接分配给父节点的其中一个子节点。
    • 案例 3:同样有效,因为不是将新节点分配给子指针的副本,而是将它分配给引用指向子指针本身的指针。在这方面,情况 2 和 3 是等价的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多