【问题标题】:Deleting Node in Linked List C++删除链表 C++ 中的节点
【发布时间】:2013-03-24 19:36:12
【问题描述】:

所以我一直在搜索论坛,但我对语言和链接列表仍然很陌生,所以我几乎无法解读结果。

基本上我为我的链表做了一个删除功能。 我目前可以创建列表,遍历列表,排序列表,搜索列表,并在链表中的任何节点之前插入。我从插入中回收了一些代码,以找到列表中可以删除的点。我的主要困惑是如何将先前的点链接到我要删除的节点之后的节点。

【问题讨论】:

  • 如果你在编写代码来做你想做的事时遇到困难,试着画出问题。我发现它对我帮助很大。另外,尽量缩进,这样代码更容易阅读。
  • 在此站点中搜索“删除链接列表中的节点”会得到大量结果,肯定其中一个对您有用吗?
  • 一个提示:看看你的while循环......它会检查以确保akey != entry->adata。然后那个循环中,检查是否entry->adata==akey。问问自己if 是否会执行。
  • 你的正确昵称!感谢您指出这一点。

标签: c++ linked-list


【解决方案1】:

我不会写一个全新的链表实现,但我可以为你指出代码的一些问题。

诀窍是在要删除的节点之前保持一个节点。

为了清楚起见,我已将 entry 重命名为 current

nodetype *current , *first, *next;
int akey;

// With this line your search will start from the second element.
// current =start->ptr;
// Should be
current = start;

// this is not needed. I am assuming the last node has NULL value for '->ptr'
// last=start;
next = current->ptr;

cout<<"Input Data You Would Like To Delete"<<endl;
cin>>akey;

// Check if the first node contains the data
// Assuming the list will have at least one element. i.e. current is not NULL 
while (current->adata == akey)
{
  // Delete it.
  delete current;
  // Update current for the while loop
  current = next;
  // update next too.
  next = current->ptr;
}
// Now we know the first element doesn't contain the data.
// Update the pointer to the begging of the new list if anything is removed from the top.
first = current;

// This has unnecessary checks. 
// ****Specifically (akey!=current->adata) will 
// prevent you from entering the loop if it is false.
// while((akey!=current->adata)&&(current->ptr !=NULL))
while(next != NULL)  // This should be enough
{
     if(next->adata == akey)
     {
          // make the current node (before the 'deletion point') 
          // lined to the one after the 'deletion point (next of the next)
          current->ptr = next->ptr; 
          // delete the node. 
          delete next;
          // Make the next pointer point to the new next. 
          next = current->ptr
     }
    // Otherwise advance both current and next.
     else {
           current = next;
           next = next->ptr; 
     }
}

// Use this to test it.
current = first;
while(current){
    cout<<current->adata<<", ";
    current = current->ptr;
}

这不是最干净的方法。但是,它与您的实现类似,因此您可以看到哪里出错了。

【讨论】:

  • 看到stardust,程序在我编译运行后仍然崩溃。
  • 好的。让我尝试在这里运行它。我还没有测试它。
  • 嗯,我正在测试东西,但我什么也没得到。
  • K 我发现我的代码有一些可怕的错误:)。我已经更新了它。看看它现在是否有效。
  • hmm 也许我没有看到我刚刚查看的更改,除非我的浏览器没有更新,否则它看起来一样。
【解决方案2】:
#include <iostream>
#include <string>
                                         // blank line(s) after includes

using namespace std;                     // some people will say to avoid this
                                         // but I use it in examples for brevity

                                         // blank line(s) around class def
class nodetype
{                                        // bracket on its own line
public:                                  // non indented visibility specifier
    nodetype(int value, nodetype *p)     // constructor first declared in class
    {
        adata = value;                   // level of indentation for fn body
        ptr   = p;                       // spaces around operators like =
    }
                                         // blank line(s) between fns and vars
    int adata;
    nodetype *ptr;
};
                                         // blank line(s) between class and fn
void LinkedListDelete(nodetype **start, int akey)
{
    nodetype *current, **previous;       // pointer *s are connected to vars
                                         // blank line between section
    previous = start;
    current  = *start;
                                         // blank line between section
                                         // I use blank lines a lot, they help
                                         // me to organize my thoughts

    while((current != NULL) && (akey != current->adata))
    {                                    // indentation inside nested scope
        previous = &current->ptr;        // no space for unary operators like &
        current  = current->ptr;         // assignments justified to same level
    }

    if (current != NULL)
    {
        *previous = current->ptr;        // no space for unary *, space for =
        delete current;
    }
                                         // more blank lines between sections
    return;
}

void LinkedListPrint(nodetype *list)     // no space for unary *
{                                        // brackets on their own lines
    while (list != NULL)                 // space around !=
    {
        cout << "(Node: " << list->adata << ") ";
        list = list->ptr;                // spaces around <<
    }
    cout << endl;
}

int main()
{
    nodetype *node = new nodetype(5, new nodetype(10, // justified stuff
                     new nodetype(7, new nodetype(14,
                     new nodetype(23, NULL)))));
                                         // blank lines
    cout << "Build linked list: ";
    LinkedListPrint(node);
    cout << "Removed node 7: ";
    LinkedListDelete(&node, 7);
    LinkedListPrint(node);

    return 0;
}

我根据您提供的代码制作了此代码。不完全一样,我改变了一些东西,但它会做你想要的。我不得不猜测 nodetype 的结构是什么,为了方便我添加了一个构造函数。我添加了一些 cmets 来指出我的风格。

请注意,它比您最初提供的代码更易于阅读。风格很重要。人们会告诉你必须使用 X 或 Y 风格,但真正重要的是你选择你喜欢的任何风格并始终如一地坚持下去;它将使您更容易快速阅读和理解自己的代码。

相信我,当您编写了大量代码时,您将无法一次记住所有代码,而能够快速弄清楚自己在做什么至关重要。

【讨论】:

    【解决方案3】:

    考虑下面给出的结构,

    struct info
    {
     int data;
     struct info *next;
    };
    

    如果您使用上述结构将记录存储在您的链表中,那么可以使用以下代码从您的链表中删除元素,

    void delitem()
    {
      info *curr,*prev;
      int tdata;
      if(head==NULL)
      {
        cout<<"\nNo Records to Delete!!!";
      }
      cout<<"\nEnter the Data to be deleted: ";
      cin>>tdata;
      prev=curr=head;
      while((curr!=NULL)&&(curr->data!=tdata))
      {
        prev=curr;
        curr=curr->next;
      }
      if(curr==NULL)
      {
        cout<<"\nRecord not Found!!!";
        return;
      }
      if(curr==head)
      {
        head=head->next;
        cout<<"\nData deleted: "<<tdata;
      }
      else
      {
        prev->next=curr->next;
        if(curr->next==NULL)
        {
          temp=prev;
        }
        cout<<"\nData deleted: "<<tdata;
      }
      delete(curr);
    }
    

    【讨论】:

    • 我通过声明结构和 void 函数更新了我的问题。迪普 head= 是什么?我是一个超级初学者。谢谢 Wug 和 Deepu,我非常感谢你们!
    • head 将包含链表中第一个元素的地址。
    • 什么是 temp 声明的?
    【解决方案4】:

    我认为删除一个节点或在链表中插入ine太简单太容易了,但它需要准确理解其机制。这个例子展示了如何添加和删除节点,但它不是一个完整的程序,但它揭示了添加和删除以及移动链表的机制:

    #include <iostream>
    using namespace std;
    
    //class Data to store ages. in a real program this class can be any other
    //class for example a student class or customer...
    class Data
             {
             public:
                   Data(int age):itsAge(age){}
                   ~Data(){}
                   void SetAge(int age){itsAge=age;}
                   int  getAge()const{return itsAge;}
             private:
                    int itsAge;
             };
    
    //the most important part of the program is the linked0list
    class Node
              {
              public:
                    //we just make itsPtrHead when created points to Null even if we pass a pointer to Data that is not NULL
                    Node(Data* pData): itsPtrData(pData),itsPtrHead(NULL),itsCount(0){}
    
                    Data* getPdata()const;
                    Node* getPnext()const;
                    int   getCount()const{return itsCount;}
    
                    void  insertNode(Data*);//import bcause it shoes the mechanism of linked-list
                    void  deleteNode(int);//most significant in this program
                    Data* findData(int&,int);
                    void  print()const;
             private:
                    Data* itsPtrData;
                    Node* itsPtrHead;
                    int   itsCount;
    
              };
    
    Data* Node::getPdata()const
    {
    if(itsPtrData)
        return itsPtrData;
    else
        return NULL;
    }
    Node* Node::getPnext()const
    {
    return itsPtrHead;
    }
    void Node::insertNode(Data* pData)
    {
    Node* pNode=new Node(pData);//create a node
    Node* pCurrent=itsPtrHead;//current node which points first to the first node that is the "head bode"
    Node* pNext=NULL;//the next node
    
    int NewAge=pData->getAge();//the new age that is past to insertNode function
    int NextAge=0;//next age
    itsCount++;//incrementing the number of nodes
    
    //first we check wether the head node "itsPtrHead" points NULL or not
    //so if it is null then we assign it the new node "pNode" and return from insert function
    if(!itsPtrHead)
        {
        itsPtrHead=pNode;
        return;
        }
    //if the condition above fails (head is not null) then check its value and
    //compare it with new age and if the new one is smaller than the head
    //make this new one the head and then the original node that head points to it make it its next node to the head
    if(itsPtrHead->getPdata()->getAge() > NewAge)
        {
        pNode->itsPtrHead=itsPtrHead;
        itsPtrHead=pNode;
        //exit the function
        return;
        }
    //if the condition above fails than we move to the next node and so on
    for(;;)
        {
        //if the next node to the current node is null the we set it with this new node(pNode) and exit
        if(!pCurrent->itsPtrHead)
            {
            pCurrent->itsPtrHead=pNode;
            return;
            }
        //else if it not null(next node to current node)
        //then we compare the next node and new node
        pNext=pCurrent->itsPtrHead;
        NextAge=pNext->getPdata()->getAge();
        //if next node's age is greater than new then we want new node 
        //to be the next node to current node then make the original next to current to be the next to its next
        if(NextAge > NewAge)
            {
            pCurrent->itsPtrHead=pNode;
            pNode->itsPtrHead=pNext;
            //exitting
            return;
            }
        //if no condition succeeds above then move to next node and continue until last node
        pCurrent=pNext;
        }
    }
    // delete a node is a bit different from inserting a node
    void Node::deleteNode(int age)
    {     
    //deleting a node is much like adding one the differecne is a bit trickier
    Node* pTmp=itsPtrHead;
    Node* pCurrent=itsPtrHead;
    Node* pNext=NULL;
    
    //1 checking for wether age (node contains age) to be deleted does exist
    for(;pTmp;pTmp=pTmp->itsPtrHead)
        {
        if(pTmp->getPdata()->getAge() == age)
            break;
        }
    //if age to be deleted doesn't exist pop up a message and return
    if(!pTmp)
        {
        cout<<age<<": Can't be found!\n";
        return;
        }
    
    int NextAge=0;
    
    for(;;)
        {
        //if age to be deleted is on the head node
        if(itsPtrHead->getPdata()->getAge() == age)
            {
            //store the next to head node
            pTmp=itsPtrHead->itsPtrHead;
            //delete head node
            delete itsPtrHead;
            //assign the head new node (node after the original head)
            itsPtrHead=pTmp;
            //decrement the count of nodes
            itsCount--;
            //exiting gracefully
            return;
            }
        //moving to next node
        pNext=pCurrent->itsPtrHead;
        NextAge=pNext->getPdata()->getAge();
        //checking next node age with age to be deleted. if they
        //match delete the next node
        if(NextAge == age)
            {
            //next node holds the target age so we want its NEXT node
            //and store it in pTmp;
            pTmp=pNext->itsPtrHead;//Next node of the target node
            //pCurrent doesn't yet hold the target age but it is the
            //previous node to target node
            //change the next node of pCurrent so that it doesn't
            //point to the target node but instead to the node right
            //after it
            pCurrent->itsPtrHead=pTmp;
            //delete the target node (holds the target age) 
            delete pNext;
            //decrement number of nodes
            itsCount--;
            //exit
            return;
            }
        //if pNext doesn't point to target node move to the next node
        //by making pCurrent points to the next node in the list
        pCurrent=pNext;
        }
    
    }
    
    void Node::print()const
    {
    Node* pTmp=itsPtrHead;
    while(pTmp)
        {
        cout<<"age: "<<pTmp->getPdata()->getAge()<<endl;
        pTmp=pTmp->itsPtrHead;
        }
    }
    int main()
    {
    //note this is not a real proram just we show how things works
    
    Data* pData=new Data(6);
    Node theNode(pData);
    theNode.print();
    pData=new Data(19);
    theNode.insertNode(pData);
    pData=new Data(20);
    theNode.insertNode(pData);
    pData=new Data(23);
    theNode.insertNode(pData);
    pData=new Data(25);
    theNode.insertNode(pData);
    pData=new Data(30);
    theNode.insertNode(pData);
    pData=new Data(27);
    theNode.insertNode(pData);
    pData=new Data(33);
    theNode.insertNode(pData);
    pData=new Data(18);
    theNode.insertNode(pData);
    
    theNode.print();
    cout<<endl<<endl;
    
    //int age;
    //int index;
    //cout<<"Age to finde: ";
    //cin>>age;
    //cout<<endl;
    //theNode.Find(index,age);
    
    //cout<<age<<" : Found on index: "<<index<<endl; 
    
    //theNode.modify(age);
    
    //theNode.print();
    int age;
    cout<<"age to delete: ";
    cin>>age;
    cout<<endl;
    
    theNode.deleteNode(age);
    theNode.print();
    
    cout<<endl<<endl<<endl;
    return 0;
    }
    //modify and other member functions are not the purpose of this program
    

    【讨论】:

      【解决方案5】:
      void Delete()
      {
          int num;
          cout<<"enter node to delete"<<endl;
          cin>>num;
          node *nodeptr=head;
          node *prev;
      
          if(head==0)
          {   
              cout<<"list is empty"<<endl;
          }
          else if(head->data==num)
              {
                node *t=head;
                head=head->next;
                delete t; 
              }   
              else
              {
              nodeptr=head;
              prev=head;
              while(nodeptr!=NULL)
              {
                  if(nodeptr->data==num)
                  {
                      prev->next=nodeptr->next;
                      node *tem=nodeptr->next;
                      delete tem;
                  }
                  prev=nodeptr;
                  nodeptr=nodeptr->next;
              }
              }
      }
      

      【讨论】:

        猜你喜欢
        • 2016-01-02
        • 2016-03-02
        • 2019-05-10
        • 2021-07-25
        • 1970-01-01
        • 1970-01-01
        • 2017-10-21
        • 2013-08-30
        • 2019-05-10
        相关资源
        最近更新 更多