0

リンクリストから要素を削除した後に表示すると、削除された要素の代わりに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
4

3 に答える 3

1

これは、前の質問に対するこの回答と密接に関連しています。

この関数をフォーマットして、詳しく見てみましょう。

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;
        }
    }
}
于 2013-01-02T10:40:26.117 に答える
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;
}
于 2013-01-02T10:11:24.887 に答える
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)を指す2つの一時的なポインターがあります。リストがリストである限り、リストをトラバースします。現在のノードがターゲットノードでない限り、終了していません。forループを終了するとき、2つの理由で終了できた可能性があります。qがNULLになり、リストが空であるか、リストにターゲットノードがないかの2つの意味を持つ可能性があるため、-1を返し、問題を報告します。またはq->data、ターゲットと等しい、つまりターゲットノードが見つかったので、それを削除しましょう。現在の値を保存してノードを削除します。削除されたノードのデータを返すのが通例です。これがお役に立てば幸いです。

于 2013-01-02T10:36:49.767 に答える