【问题标题】:C++ Add node to beginning of linked list fails after 1 time. Trouble with other methods tooC++ 将节点添加到链表的开头 1 次后失败。其他方法也有问题
【发布时间】:2013-11-18 19:27:17
【问题描述】:

所以我有一个半工作的链表程序。我只是在使用某些方法时遇到了一些问题......我记录的那些 bekiw 正在工作,除了 delete from end 这表现得很奇怪。

我在 Mavericks 上使用 NetBeans,G++ 作为我的编译器和 C++11 Here is a zip of all of the program files

以下是我正在尝试的方法列表:

//working
int size() const;
/kind of 
void addToStart(Node *);
//working
void addToEnd(Node *);
//working
void printList();
//working
bool removeFromStart();
//kind of working
bool removeFromEnd();

//Still working on these
void removeNodeFromList(int);
void removeNodeFromList(string);

现在,我必须运行 removeFromEnd() 两次才能使其工作。意思是,我在程序开始时运行它一次,它什么也不做,但随后的每一次,它实际上都会删除。

对于 addToStart(),如果我只运行一次它就可以工作。即:

  • 我可以在程序开始时运行一次并打印出列表
  • 我可以在使用 addToEnd 后运行一次,但如果我再次尝试并尝试打印列表,它只会不断吐出我尝试添加的值。

addToEnd() 如果我继续运行它,它可以完美地找到,但如果我:

首先使用 addToEnd() 添加项目,然后使用 addToStart() 一次,然后尝试再次使用 addToEnd()。当我打印出列表时,它只打印出两个对象,每个对象都是我尝试插入的最后一个值的副本。

void LinkedList::addToEnd(Node* ne) 
{
    Node** q = &myHead;
    while (*q) 
    {
        q = &(*q)->next;
    }

    *q = new Node(ne->itemName, ne->itemNo);
}

void LinkedList::printList() 
{
    Node* p = myHead;
    while (p != NULL) 
    {
        cout << p->itemNo << " " << p->itemName;
        cout << endl;
        p = p->next;
    }

    cout << endl << endl;
}

bool LinkedList::removeFromStart() 
{
    if (myHead == NULL) 
    {
        cout << "List is already empty";
    }
    else 
    {
        myHead = myHead->next;
    }
}

bool LinkedList::removeFromEnd() 
{
    if (myHead == NULL) 
        return false;

    //Empty the list if there's only one element
    if (myHead->next == NULL) 
    {
        delete myHead;
        myHead = NULL;
        myTail = NULL;
        return true;
    }

    // Find the last item in the list
    Node *temp = myHead;
    while (temp->next != myTail) 
    {
        temp = temp->next;
    }

    delete myTail;
    temp->next = NULL;
    myTail = temp;
    return true;
}

另外,仍在尝试找出删除的内容

void LinkedList::removeNodeFromList(int i) {


//Save the values
Node* p = myHead;
Node* temp = myHead->next;


    while (p) {

        if (p->itemNo == i) {

            p=temp;
        } else {
            p = p->next;
        }

    }

}

【问题讨论】:

  • 请更正您的格式并给出一个显示错误行为的示例程序
  • 修复了格式。为了在不添加所有内容的情况下保持问题简短,我链接到一个包含我所有代码的 zip。
  • 您能否将范围缩小到 一个 您遇到的问题?我数了五个,你甚至都懒得准备minimal complete example

标签: c++ pointers reference linked-list


【解决方案1】:

你有一个tail 指针,那么你为什么要遍历列表来找到结尾呢?另外,为什么要通过指针传递节点?

void LinkedList::addToEnd(Node ne) 
{
    if (myHead == nullptr) // empty list
    {
        myHead = myTail = new Node(ne);
        myTail->next = nullptr;
    }
    else
    {
        myTail->next = new Node(ne); // assuming Node has an accessible copy constructor
        myTail = myTail->next;
    }
}

removeFromStart 函数存在内存泄漏:

bool LinkedList::removeFromStart() 
{
    if (myHead == nullptr) 
    {
        cout << "List is already empty";
        return false;
    }


    Node* temp = myHead;
    myHead = myHead->next;
    if (myTail == temp) // if there is only 1 element in the list, head == tail
    {
        myTail = myhead;
    }
    delete temp;
    return true;
}

据推测,removeFromEnd 应该是去掉尾巴:

bool LinkedList::removeFromEnd() 
{
    if (myTail == nullptr) 
        return false;

    // unless you have a doubly-linked list, loop to find 1 before the tail
    Node* temp = nullptr;
    for (temp = myHead; temp && temp->next != myTail; temp = temp->next);


    if (myHead == temp) // when there is only 1 element in the list, head == tail
    {
        delete temp->next;
        myHead = nullptr;
        myTail = nullptr;
    }
    else
    {
        delete temp->next;
        temp->next = nullptr;
        myTail = temp;
    }
    return true;
}

是的,你正在使用new(在你的addtoEnd函数中),所以你必须使用delete不是free!)。

旁注:您可以使用std::unique_ptr 更好地编写删除代码(实际上您可以通过在任何地方使用它来改进代码的整体),这将使您的代码每行大约 4 行。我将把它留给你实现。

【讨论】:

  • 感谢您的想法,我现在要尝试一下。抱歉,一定是错过了那个新声明。
【解决方案2】:

您有一个名为 myTail 的成员,您似乎在使用“有时”

在 addFromEnd 中,您不会更新 myTail。 在其中一个删除功能中,您不会更新 myTail,即使您可能会更改它 但在 RemoveFromTail 中,您正在尝试使用它。

myTail 没有理由包含有效值,当您尝试使用它时,您可能会收到错误(因为节点可能已被删除)或意外结果,因为它只是指向列表中的某个位置。

您应该丢失它(因为您可以轻松找出尾部。它是 next==NULL 的节点)或在每次更改列表的调用中注意维护它(仅当尾部受到明显影响时)

由于您使用的是 c++11,因此有一些建议:

  • 使用 nullptr 代替 NULL
  • 将 std::unique_ptr 用于 Next。它将负责“删除”您不再使用的节点。
  • 为节点使用复制 ctor。如果您曾经对 Node 进行过更改,则无需重新访问这部分代码,只需重新访问构造函数即可。
  • 如果您持有列表中对象的副本。那么如果你的界面接受const Node&amp;而不是Node*,那就更清楚了。对我来说,Node* 让您看起来像是要使用用户提供的 ptr。
  • 【讨论】:

    • 我只是注意到了这一点,然后输入了我目前正在尝试的内容。我没有使用 new 来分配它们。
    • 他只需要在列表末尾添加或删除项目时更新myTail
    • 是的,但 removeNodeFromList 可能最终会从列表末尾删除,这就是为什么他需要考虑 myTail 可能会在更改列表的方法中受到影响
    • @odedsh 同意,但仅在尾部受到影响时。
    猜你喜欢
    • 2021-06-28
    • 1970-01-01
    • 2012-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多