头在链表中没有正确链接

时间:2013-01-02 10:08:38

标签: c++ linked-list

从链表中删除元素后显示时,显示0代替删除的元素。我无法更新节点。任何人都可以解释发生了什么?为什么显示0?

#include<iostream>
#include<stdlib.h>
using namespace std;

    class node {

    public:
      int data;
      node *link;

    };

    class linkedlist {

        node *head;

    public:

        linkedlist() {
            head=NULL;
        }

        int add(int data1) {

            node *insertnode=new node;
            insertnode->data=data1;
            insertnode->link=NULL;

            node *temp=head;

            if(temp!=NULL)
            {
                while(temp->link!=NULL)
                {
                    temp=temp->link;
                }
                temp->link=insertnode;

            }
            else{head=insertnode;}

        }

        void disp()
        {
            node *temp1=head;
            cout<<endl;
            if(temp1==NULL)
            {
                cout<<"Empty"<<endl;
            }

            if(temp1->link==NULL)
            {
                cout<<temp1->data<<endl;

            }
            else {

                do {
                    cout<<temp1->data<<endl;
                    temp1=temp1->link;
                } while(temp1!=NULL);

            }

        }

        int remove(int removedata)
        {
            node *previous;
            node *temp2=head;
            if(temp2==NULL)
                {exit(0);}

            if(temp2->link==NULL)
            {
                delete temp2;
                head=NULL;
            }

            else
            {

                while(temp2!=NULL)
                {

                    if(temp2->data==removedata)
                    {
                        previous=temp2;
                        delete temp2;
                    }

                    temp2=temp2->link;

                }

            }

        }

    };

    int main()
    {

        linkedlist list;
        list.add(10);
        list.add(100);
        list.add(200);
        list.remove(10);
        list.disp();

    }

显示的输出是:

0
100
200

3 个答案:

答案 0 :(得分:1)

您已删除了头节点,但如果发生这种情况,代码中的任何内容都不会重新分配头节点。

所以你在这里有未定义的行为。

您也这样做:

if(temp2->data==removedata)
{
    previous=temp2;
    delete temp2;
}
temp2=temp2->link;

换句话说,你删除了一些东西,然后取消引用它。我不确定previous应该在这里做什么,但现在包含指向已被删除的内容的指针。幸运的是,这似乎是它唯一引用的地方(这里的目的是什么?)

你的函数似乎没有返回任何东西,但它被声明为返回一个int。

所以我觉得这里的逻辑都是错的。

您需要做的是:

  • 如果您的节点是头节点,请将头节点指向您要删除的节点的下一个节点。
  • 否则,找到上一个节点(下一个要删除的节点所在的节点),并更新该节点以指向待删除节点的下一个节点。
  • 删除节点,现在没有任何内容引用它。

像这样(未经测试):

if(head == NULL) return; // List is empty.

node *prev = head;
if(prev->data == removedata)
{
    head = prev->link;
    delete prev;
    return; // removed the head node
}
while(prev->link)
{
    if(prev->link->data == removedata)
    {
        node *t = prev->link;
        prev->link = t->link;
        delete t;
        return; // removed a non-head node
    }
    prev = prev->link;
}
// data is not in the list

或者如果你想尝试聪明并消除特殊情况:

node **prevptr = &head;
node *cur = head;
while(cur)
{
    if(cur->data == removedata)
    {
        *prevptr = cur->link;
        delete cur;
        break;
    }
    prevptr = &cur->link;
    cur = cur->link;
}

答案 1 :(得分:1)

我可以建议我的代码吗?

int removeData(int target)
{
  //Let's return -1 if we can't find the target element.
  node *p,*q;
  for(q=head;q!=NULL && q->data!=target;p=q,q=q->link)
     ;
  if(q==NULL)
  {
    //Either the list was empty or the target element was not on the list
    return -1;
  }
  else
  {
    //We found the element, let's delete it.
    int ret=q->data;
    if(q==head)//If target node is the first node in list
      head=q->link;
    else
      p->link=q->link;
    delete q;//We delete the node pointed to by q here, which is our target node
    return ret;  
  }  
}  

让我解释一下上面的代码。首先我们有两个临时指针,指向前一个节点( p )和当前节点( q )我们遍历链表。只要列表没有结束或只要当前节点不是我们的目标节点,我们就会遍历列表。 当我们退出for循环时,我们可以退出两个原因。 q 都变为NULL,这可能有两个含义,要么我们的列表为空,要么我们的列表没有目标节点。所以我们返回-1,报告问题。 或者q->data等于target,这意味着我们找到了我们的目标节点,让我们删除它。我们存储当前值并删除节点。通常会返回已删除节点的数据。希望这有帮助。

答案 2 :(得分:1)

这与this answeryour previous question密切相关。

让我们格式化这个功能,仔细看看。

int remove(int removedata)
{
    node* previous;     // Why is this unintialised?
    node* temp2 = head; // Can you think of a more meaningful name for this
                        // variable? Perhaps "current"?
    if (temp2 == NULL)
    {
        exit(0); // Do you really want to exit the program if you try to
                 // remove an item from an empty list? Is there a better way
                 // to handle this?
    }

    if(temp2->link == NULL) // What is so special about a linked list with one element?
    {
        delete temp2; // You've not checked to see if this element is
                      // `removedata`
        head = NULL;  // So calling this function for any list with one element
                      // results in an empty list. This is probably
                      // undesirable
    }
    else
    {
        while (temp2 != NULL) // Consider using a for-loop for iteration. It
                              // couples the increment(s) with the
                              // terminating condition.
        {
            if (temp2->data == removedata) // At this point we have found
                                           // our candidate for removal
            {
                previous = temp2; // This is not the "previous" node, but
                                  // the "current" one. And this variable is
                                  // never used. You do need to know where
                                  // the previous node is and whether it is
                                  // 'head' to update either the 'link' or
                                  // 'head'

                delete temp2;     // This does remove the correct node but
                                  // leaves the previous 'link' pointer
                                  // dangling and any subsequent nodes are
                                  // orphaned.
            }
            temp2 = temp2->link; // See comment above about for-loops.
        }
    }
} // This function is declared `int` but has no return statement.

替代实现可能看起来像这样(未经测试):

void remove(int removedata)
{
    for (node* current = head, * previous = NULL;
        current;
        previous = current, current = current->link)
    {
        if (current->data == removedata)
        {
            if (previous)
            {
                previous->link = current->link;
            }
            else
            {
                head = current->link;
            }
            delete current;
            break;
        }
    }
}