C++将节点添加到链表的开头一次后失败.其他方法也有问题



所以我有一个半工作的链表程序。我只是在某些方法上遇到了一些麻烦。。。。我记录的那些bekiw正在工作,除了从结尾删除,这表现得很奇怪。

我在Mavericks上使用NetBeans,C++作为我的编译器,C++11这是所有程序文件的zip

以下是我尝试制作的方法列表:

//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(),如果我只运行一次,它就可以工作。I.E:

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

addToEnd()工作得很好,如果我只是继续运行它,但如果I:,它会失败

首先使用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;
        }
    }
}

您有一个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更好地编写remove代码(实际上,您可以通过在任何地方使用它来改进代码的整体性),这将使您的代码每行大约有4行长。我把它留给你来执行。

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

在addFromEnd中,您不会更新myTail。在其中一个remove函数中,即使您可能会更改myTail,也不会更新它但在RemoveFromTail中,您正试图使用它。

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

您应该丢失它(因为您可以很容易地找出尾部。它是next==NULL的节点),或者在每次更改List的调用中小心维护它(只有尾部明显受到影响时)

由于您使用的是c++11,因此有以下几点建议:

  • 使用nullptr而不是NULL
  • 使用std::unique_ptr作为Next。它将负责"删除"您不再使用的节点。
  • 对Node使用复制ctor。如果您对Node进行了更改,则不需要重新访问代码的这一部分,只需要重新访问构造函数。
  • 如果您持有列表中对象的副本。那么,您的界面是否会接受const Node&而不是Node*就更清楚了。对我来说,Node*让人觉得你要使用用户提供的ptr。
  • 相关内容

    • 没有找到相关文章

    最新更新