指针 - 将 ptr 传递给 ptr 或传递 ptr 的地址

发布于 2024-12-12 17:28:08 字数 1960 浏览 1 评论 0原文

我正在尝试使用两种方法删除示例二叉搜索树的左子节点 (10):

  • 方法 1:通过将指针传递给当前节点的指针。
  • 方法2:通过将指针的地址传递给当前节点。这不会删除节点,但调用删除会破坏指针排列,导致打印节点时崩溃。

树看起来像这样,我正在尝试删除 10 并将其替换为 5

<前><代码> 20 | 10--|---30 | 5---|

我对指针有一些了解。但是,我仍然不清楚指针的这种行为。

#include <iostream>
class Node
{
public:
    Node(int key) : leftChild(0), rightChild(0), m_key (key){}
    ~Node(){}

    Node *leftChild;
    Node *rightChild;
    int m_key;
};

Node* build1234(int, int, int, int);
void print(Node *);
void print1234(Node *);

void removeLeft(Node **nodePtr)
{
    Node *oldPtr = *nodePtr;
    if(*nodePtr)
    {
        *nodePtr = (*nodePtr)->leftChild;
        delete oldPtr;
    }
}

int main()
{
    Node *demo1 = build1234(10, 20, 30, 5);
    Node *demo2 = build1234(10, 20, 30, 5);
    print1234(demo1);
    print1234(demo2);

    //Method1 - 10 is correctly removed with 5
    Node **nodePtr = &demo1;
    nodePtr = &(*nodePtr)->leftChild;
    removeLeft(nodePtr);
    print1234(demo1);

    //Method2 - 10 is not removed
    Node *node = demo2;
    node = node->leftChild;
    removeLeft(&node);
    print1234(demo2);       
    return 0;
}

Node* build1234(int B, int A, int C, int D)
{
    Node *root = new Node(A);
    root->leftChild = new Node(B);
    root->rightChild = new Node(C);
    root->leftChild->leftChild = new Node(D);
    return root;
}
void print(Node *node)
{
    if(node)
    {
        print(node->leftChild);
        std::cout << "[" << node->m_key << "]";
        print(node->rightChild);
    }
}

void print1234(Node *node)
{
    std::cout << std::endl;
    print(node);
}

注意:这个问题不是关于 BST 的,而是关于指针的。如果您在 main() 函数中看到对 removeLeft(nodePtr)removeLeft(&node) 的两次调用。

  1. 这两者有何不同?
  2. 为什么第二种方法达不到预期的效果呢?

I am trying to remove the left child (10) of a sample binary search tree using two methods:

  • Method1: By passing pointer to a pointer to the current node.
  • Method2: By passing address of the pointer to the current node. This does not removes the node, but calling delete corrupts the pointer arrangement, causing a crash while printing the nodes.

The tree looks like this and I am trying to delete 10 and replace it with 5

       20
       |  
   10--|---30
    |
5---|

I have some understanding of pointers. But still, I am not clear with this behavior of pointers.

#include <iostream>
class Node
{
public:
    Node(int key) : leftChild(0), rightChild(0), m_key (key){}
    ~Node(){}

    Node *leftChild;
    Node *rightChild;
    int m_key;
};

Node* build1234(int, int, int, int);
void print(Node *);
void print1234(Node *);

void removeLeft(Node **nodePtr)
{
    Node *oldPtr = *nodePtr;
    if(*nodePtr)
    {
        *nodePtr = (*nodePtr)->leftChild;
        delete oldPtr;
    }
}

int main()
{
    Node *demo1 = build1234(10, 20, 30, 5);
    Node *demo2 = build1234(10, 20, 30, 5);
    print1234(demo1);
    print1234(demo2);

    //Method1 - 10 is correctly removed with 5
    Node **nodePtr = &demo1;
    nodePtr = &(*nodePtr)->leftChild;
    removeLeft(nodePtr);
    print1234(demo1);

    //Method2 - 10 is not removed
    Node *node = demo2;
    node = node->leftChild;
    removeLeft(&node);
    print1234(demo2);       
    return 0;
}

Node* build1234(int B, int A, int C, int D)
{
    Node *root = new Node(A);
    root->leftChild = new Node(B);
    root->rightChild = new Node(C);
    root->leftChild->leftChild = new Node(D);
    return root;
}
void print(Node *node)
{
    if(node)
    {
        print(node->leftChild);
        std::cout << "[" << node->m_key << "]";
        print(node->rightChild);
    }
}

void print1234(Node *node)
{
    std::cout << std::endl;
    print(node);
}

Note: This question is not about BST, but pointers. If you see the two calls to removeLeft(nodePtr) and the removeLeft(&node) in the main() function.

  1. How are these two different?
  2. Why the second method fails to achieve the desired result?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

烟花肆意 2024-12-19 17:28:08

在第一种情况下,您传递的是树中存在的指针的地址,因此您直接修改树的内容。

在第二种情况下,您传递的是 main() 本地变量的地址。树没有被修改,从地址删除是访问栈内存,这就是崩溃的原因

In the first case, you are passing an address of a pointer that exists in the tree, so you are modifying the contents of the tree directly.

In the second case, you are passing an address of a variable that is local to main() instead. The tree is not modified, and deleting from the address is accessing stack memory, which is why it crashes

ㄖ落Θ余辉 2024-12-19 17:28:08

你想太多了。您所需要的只是一个函数 removeLeft(Node*) ,它可以递归地解开左侧节点并删除它:

void removeLeft(Node * p)
{
  removeBoth(p->leftChild); // recurse, OK if null

  delete p->leftChild;  // OK if already null
  p->leftChild = 0;     // necessary to make recursion terminate
}

void removeBoth(Node * p)
{
  if (!p) return;

  removeLeft(p);
  removeRight(p);
}

You're overthinking it. All you need is a function removeLeft(Node*) that unhooks the left node and deletes it, recursively:

void removeLeft(Node * p)
{
  removeBoth(p->leftChild); // recurse, OK if null

  delete p->leftChild;  // OK if already null
  p->leftChild = 0;     // necessary to make recursion terminate
}

void removeBoth(Node * p)
{
  if (!p) return;

  removeLeft(p);
  removeRight(p);
}
素手挽清风 2024-12-19 17:28:08

如果您不擅长使用指针,请考虑使用智能指针。
使用智能指针时,使用 shared_ptr 代替 Node * 并使用 make_shared(new Node); 代替 new Node code> 并删除所有删除内容。现在您可以处理指针而无需关心删除和内存损坏。

If you are bad with pointers consider using smart pointers.
When using smart pointers use shared_ptr<Node> instead of Node * and make_shared(new Node); instead of new Node and remove all deletes. now you can handle pointers without caring for deletes and memory corruption.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文