如何删除节点指针

时间:2017-11-18 20:16:36

标签: c++

这是功课。我还没有看到任何真正能够直接解决这个问题的事情,所以我很难解决这个问题。我必须创建一个最大堆的链接节点实现,并且我在删除一个值后很难删除一个节点。

我的代码:

template<class ItemType>
BinaryHeapNode<ItemType>* LinkedMaxHeap<ItemType>::getLastNode()
{
    BinaryHeapNode<ItemType>* lastNode = rootPtr->getRightSiblingPtr();
    BinaryHeapNode<ItemType>* prevLastNode = rootPtr;
    while(lastNode != nullptr)
{
    prevLastNode = lastNode;
    lastNode = lastNode->getRightSiblingPtr();      
}
return prevLastNode;
}

template<class ItemType>
bool LinkedMaxHeap<ItemType>::removeValue(ItemType value)
{
    BinaryHeapNode<ItemType>* tempNode = rootPtr;
    for (int i = 0; i < itemCount; i++)
    {
        if(tempNode->getItem() == value)
        {
            tempNode->setItem(getLastNode()->getItem());//set item
            delete getLastNode();                       //delete last node
            getLastNode() = nullptr;                    //set last node null
            getLastNode()->setRightSiblingPtr(nullptr); //last node should be different
            itemCount--;                                //set it's sibling to null
            heapRebuild(tempNode);
        }

        tempNode = tempNode->getRightSiblingPtr();
    }

    return true;
}

我的问题是getLastNode()= nullptr。 VS告诉我getLastNode()不是左值。这对我没有意义,因为getLastNode正在返回一个指向BinaryHeapNode的指针,但它不能将该指针设置为nullptr?

我认为这可能是我的指针逻辑问题(最好是不稳定的)所以我想改变getLastNode()只返回一个节点会有所帮助。那没有。所以我试着弄乱&amp;运算符并返回最后一个节点的地址。毋庸置疑,我还没有找到解决方案。如果有人能提供某种方向,我们将不胜感激。我不完全确定它为什么不起作用。

编辑:

根据arynaq提到的内容编辑代码。错误消失了,但现在我有一堆链接器错误,我必须先修复它才能测试它。这段代码会做我想要的吗?我觉得它只是删除nodeToDelete而不是删除堆中的节点。

template<class ItemType>
bool LinkedMaxHeap<ItemType>::removeValue(ItemType value)
{
    BinaryHeapNode<ItemType>* tempNode = rootPtr;
    BinaryHeapNode<ItemType>* nodeToDelete = getLastNode();
    for (int i = 0; i < itemCount; i++)
    {
        if(tempNode->getItem() == value)
        {
            tempNode->setItem(nodeToDelete->getItem());
            delete &nodeToDelete;
            nodeToDelete = nullptr;
            getLastNode()->setRightSiblingPtr(nullptr);
            itemCount--;
            heapRebuild(tempNode);
        }

        tempNode = tempNode->getRightSiblingPtr();
    }

    return true;
}

1 个答案:

答案 0 :(得分:0)

好的,我会尝试通过解释有关指针的一些内容来提供帮助。希望这会澄清一些误解并帮助你完成任务。

当您获得指针的副本时:mypointer* p = get_pointer();然后删除它, 删除内存。但是,当您将nullptr分配给此局部变量时,它不会影响&#34;源&#34;你的指针。

这是一个详细的例子,显示出现问题的地方。如果您从未将v[0]设置为nullptr

#include <iostream>
#include <vector>

struct Object {
    ~Object() {
        std::cout << "Object destructor." << std::endl;
    }
    int val = 42;
};

struct OtherObj {
    int val = 322;
};

void print_vec(const std::vector<Object*>& v) {
    for (const auto& x : v) {
        std::cout << x << std::endl;
    }
}

int main(int, char**) {
    // Init vector and print addresses.
    std::vector<Object*> v(2);
    print_vec(v);

    // Init objects in vector and printit.
    for (auto& x : v) {
        x = new Object();
    }
    print_vec(v);

    // Get a copy of a pointer and delete that. All good so far.
    Object* pointer_to_delete = v[0];
    delete pointer_to_delete;

    // Assign nullptr to the temporary local pointer.
    // Does nothing to the pointer in the vector.
    pointer_to_delete = nullptr;

    // Print the vector to prove it.
    print_vec(v);

    // On a non debug build, the memory will still have the last value.
    // Careful! Cause of headaches here. This should be set to nullptr.
    std::cout << v[0]->val << std::endl; // "No problem", certainly not nullptr.

    // Now that we allocate a new object, v[0] will be overwritten.
    OtherObj* bad_bad_boy = new OtherObj();
    // Print the address of the new object, to show it was created at
    // the old v[0] address.
    std::cout << bad_bad_boy << std::endl;

    // Bad things ensue...
    std::cout << v[0]->val << std::endl;

    return 0;
}

clang上的输出是:

0x0
0x0
0x7ffa21c026c0
0x7ffa21c026d0
Object destructor.
0x7ffa21c026c0
0x7ffa21c026d0
42
0x7ffa21c026c0
322

如您所见,将本地指针设置为nullptr是不够的!我希望这能为你解决一些问题:)

Online version