C++ nullptr=节点未正确分配

C++ nullptr=节点未正确分配,c++,pointers,avl-tree,C++,Pointers,Avl Tree,请不要太深入我,我仍在稳步学习,在尝试构建AVL树时遇到了一个问题。在insert上迭代树时,我会一直到到达一个nullptr,创建一个新节点,并将该ptr分配给nullptr。但这个值永远不会被接受。有人能找出错误并向我解释一下吗?泰 #ifndef AVLTree_hpp #define AVLTree_hpp #include <stdio.h> #include <stack> template<typename T> class AVLTree{

请不要太深入我,我仍在稳步学习,在尝试构建AVL树时遇到了一个问题。在insert上迭代树时,我会一直到到达一个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 */


\ifndef AVLTree\u水电站
#定义AVLTree_水电站
#包括
#包括
模板
类AVLTree{
私人:
结构节点{
T值;
节点*左;
节点*右;
内部高度;
节点(TV)
:左{nullptr},右{nullptr}
{
val=V;
}
~Node(){
}
};
节点*头;
void rightRotate(节点*&节点);
void leftRotate(节点*&节点);
void leftRight(节点*&节点);
void right left(节点*&节点);
公众:
AVLTree();
~AVLTree();
AVLTree(const AVLTree&c);
AVLTree(AVLTree&c);
AVLTree&operator=(常量AVLTree&c);
AVLTree&operator=(AVLTree&c);
空加(T值);
int getHeight(节点*n);
};
模板
AVLTree::AVLTree()
:head{nullptr}{
}
模板
AVLTree::~AVLTree(){
}
模板
void AVLTree::rightRotate(节点*&节点){
节点*温度=节点;
节点=节点->左;
Node*leftLL=Node->right;
temp->left=leftLL;
节点->右侧=温度;
}
模板
void AVLTree::leftRotate(节点*&节点){
节点*温度=节点;
节点=节点->右侧;
节点*yL=节点->左;
温度->右=yL;
节点->左=温度;
}
//左右条件
模板
void AVLTree::leftRight(节点*&节点){
左旋转(节点->左);
右旋转(节点);
}
//左右条件
模板
void AVLTree::rightLeft(节点*&节点){
右旋转(节点->右);
左旋转(节点);
}
模板
void AVLTree::add(T值){
if(head==nullptr){
head=新节点(值);
返回;
}
std::stack st;
节点*it=头部;
while(it!=nullptr){
圣普什(it);
if(值val){
it=it->left;
}否则{
it=it->right;
}
}
//此处是未将其分配给新节点指针的位置。
//我已经对它进行了测试,并且创建了节点,“它”在任何点上都不包含值。
它=新节点(值);
整数计数=0;
而(!st.empty()){
int balance=getHeight(圣上()->左)-getHeight(圣上()->右);
如果(余额>1){
if(st.top()->left!=nullptr&&st.top()->left!=nullptr){
左旋转(st.top());
}否则{
左-右(st.top());
}
}else if(balanceright!=nullptr&&st.top()->right!=nullptr){
右旋转(圣托普());
}否则{
右左(圣托普());
}
}
圣普();
如果(++计数==4){
打破
}
}
}
模板
intavltree::getHeight(节点*n){
int max=0;
如果(n!=nullptr){
max=std::max(getHeight(n->left),getHeight(n->right))+1;
}
返回最大值;
}
#endif/*AVLTree_水电站*/

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

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;
}
Node*it=head;
布尔左=真;
while(it!=nullptr){
圣普什(it);
左=值val;
如果(左){
it=it->left;
}否则{
it=it->right;
}
}
它=新节点(值);
如果(左){
stack.top()->left=it;
}否则{
stack.top()->right=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;
}
Node*it=head;
布尔左=真;
while(it!=nullptr){
圣普什(it);
左=值val;
如果(左){
it=it->left;
}否则{
it=it->right;
}
}
它=新节点(值);
如果(左){
stack.top()->left=it;
}否则{
stack.top()->right=it;
}

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

#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;
}
  • 情况1:不起作用,因为新的
    节点
    被分配给左/右子指针的副本(即,不是父节点的实际子节点)
  • 情况2:按预期工作,因为新节点直接分配给父节点的子节点之一
  • 情况3:也可以工作,因为您没有将新节点分配给子指针的副本,而是将其分配给引用指向子指针本身的指针。在这方面,情况2和3是等效的

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

      #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;
      }
      
      • 情况1:不起作用,因为新的
        节点
        被分配给左/右子指针的副本(即,不是父节点的实际子节点)
      • 情况2:按预期工作,因为新节点直接分配给父节点的子节点之一
      • 情况3:也可以工作,因为您没有将新节点分配给子指针的副本,而是将其分配给引用指向子指针本身的指针。在这方面,情况2和3是等效的

      您所说的“值始终不被接受”是什么意思?在运行程序时这是如何表现的(异常、segfault、无效状态等)?修改堆栈
      st
      中的元素对复制它的树节点没有影响。指针没有什么特别之处。但“值永远不会被接受”是什么意思?在运行程序时这是如何表现的(异常、segfault、无效状态等)?修改堆栈
      st
      中的元素对复制它的树节点没有影响。指针没有什么特别之处。