【问题标题】:Why is my doubly linked list remove function deleting multiple nodes?为什么我的双向链表删除功能会删除多个节点?
【发布时间】:2020-05-23 13:08:56
【问题描述】:

我正在用 C++ 编写双向链表的代码。我是 C++ 的初学者,所以请原谅我问这个问题。我正在用数字(1、2、3、...、n)填充双向链表。我首先使用搜索功能并找到包含我要删除的值的节点。然后我调用 remove 函数来删除节点。我的删除功能似乎不仅要删除一个节点,而且我一直在绞尽脑汁想弄清楚。我认为这可能是因为我的 DList 类没有析构函数,但我不确定如何实现它,因为我要删除的结构是 ListNode。任何见解将不胜感激。谢谢。

例如。测试用例 n = 8

删除前的列表:1 2 3 4 5 6 7 8

删除后的列表:7

DLIST.H

#ifndef DLIST_H
#define DLIST_H

struct ListNode 
{
  /* define your list node type */
  int val;
  ListNode* next;
  ListNode* prev;
};

class DList
{
  public:
  DList();
  /* implement copy constructor, assignment, destructor if needed */
  void add_to_front(int value);
  void add_to_back(int value);
  int first();
  int last();
  void remove(ListNode* node);
  void display();
  ListNode* previous(ListNode* node);
  ListNode* next(ListNode* node);
  ListNode* search_value(int value);

  private:
  /* declare your data */
  ListNode* head;
  ListNode* tail;
};

#endif

DLIST.CC

#include "dlist.h"
#include <cstddef>
#include <cstdlib>
#include <cstdio>
#include <iostream>

      //ListNode* head;
      //ListNode* tail;

      DList::DList(){
         head = NULL;
         tail = NULL;
      }

      void DList::add_to_front(int value){ 
         if (head != NULL){
            //std::cout<<"addfront1\n";
            ListNode *newhead = new ListNode();
            newhead->val = value;
            //std::cout<<"addfront1 val" << newhead->val << "\n";
            newhead->next = head;
            newhead->prev = NULL;
            head->prev = newhead;
            head = newhead;
         }else{
            //std::cout<<"addfront2\n";
            ListNode *newhead = new ListNode();
            newhead->val  = value; 
            //std::cout<<"addfront2 val" << newhead->val << "\n";
            newhead->prev = NULL; 
            newhead->next = NULL;
            head = newhead;   
            tail = newhead;
         }
      }    

      void DList::add_to_back(int value){
         if (tail != NULL){
            //std::cout<<"addback1\n";
            ListNode *newtail = new ListNode();
            newtail->val = value;
            //std::cout<<"addback1 val" << newtail->val << "\n";
            newtail->next = NULL;
            newtail->prev = tail;
            tail->next = newtail;
            tail = newtail;
         }else{
            //std::cout<<"addback2\n";
            ListNode *newtail = new ListNode();
            newtail->val = value;
            //std::cout<<"addback2 val" << newtail->val << "\n";
            newtail->prev = NULL;
            newtail->next = NULL;
            tail = newtail;
            head = newtail;
         }
      }

      int DList::first(){
         return head->val;
      }

      int DList::last(){
         return tail->val;
      }

      void DList::remove(ListNode* node){

         std::cout << "want to del value is " << node->val  << "\n";
         ListNode *toDelete = new ListNode();
         if (head == NULL || tail == NULL){
            return;
         }

         if(head->val == node->val){
            toDelete = head;
            head = node->next;
            if (head != NULL){
               head->prev = NULL;
            }
            std::cout << "del1 value is " << toDelete->val  << "\n";
            delete(toDelete);
         }else if(tail->val == node->val){
            toDelete = tail;
            tail = node->prev;
            std::cout << "del2 newtail value is " << node->prev->val  << "\n";
            if (tail != NULL){
               tail->next = NULL;
            }
            std::cout << "del2 value is " << toDelete->val  << "\n";
            delete(toDelete);
         }else if (node != NULL){
            std::cout << "node1 value is " << node->val  << "\n";
            node->prev->next = node->next;
            node->next->prev = node->prev;
            std::cout << "node2 value is " << node->val  << "\n";
            delete(node);
         }
      }

      ListNode* DList::previous(ListNode* node){
         if(node->prev != NULL){
            return node->prev;
         }else{
            return node;
         }
      }

      ListNode* DList::next(ListNode* node){
         if(node->next != NULL){
            return node->next;
         }else{
            return node;
         }
      }

      ListNode* DList::search_value(int value){
         //std::cout << "head.0\n";
         //std::cout << "head value is " << head->val  << "\n";
         while(head->next != NULL){
            //std::cout << "head.1\n";
            if(head->next->val == value){
               //std::cout << "head.2\n";
               return head->next;
            }else{
               //std::cout << "head.3\n";
               head = head->next;
            }
         }
         if (head->next == NULL){
            if (head->val == value){
               return head;
            }else{
               //std::cout << "error\n";
            }
         }

      }

      void DList::display(){
         std::cout<<"Element In The Linked List Are : ";
         ListNode *disp= new ListNode;
         disp = head;
         while(disp!=NULL)
         {
             std::cout<<" "<<disp->val;
             if(disp->next==NULL)
             {
                 std::cout<<"\n";
                 break;
             }
             disp=disp->next;
         }
      }

DLIST_TEST.CC

#include <cassert>
#include <cstdlib>
#include <cstdio>
#include <ctime>
#include <iostream>
#include <iomanip>
#include "dlist.h"
using namespace std;

int main (int argc, char* argv[])
{
  int N = -1;
  if (argc == 2) {
    N = atoi (argv[1]);
    assert (N > 0);
  } 
  //cout << "N is " << N << "\n";
  DList testList = DList();
  int i = 0;
  while(i<N){
    //cout << "i value is "<< i << "\n";
    testList.add_to_back(i+1);
    //cout << "second\n";
    i++;
  }
  int randn = rand() % N + 1;// randn in the range 1 to N
  cout << "randn is "<< randn <<"\n";
  testList.display();
  clock_t t1,t2;
  t1=clock();

  ListNode* loc = testList.search_value(randn);
  cout << "loc value is "<< loc->val <<"\n";
  testList.remove(loc);

  t2=clock();

  float diff ((float)t2-(float)t1);
  float seconds = diff / CLOCKS_PER_SEC;
  cout<<"\nTime taken by function: "<<seconds<<" seconds\n" << endl;  

  testList.display();
  testList.add_to_front(N);
  testList.display();


  return 0;
}

【问题讨论】:

  • 第一个错误:ListNode *toDelete = new ListNode(); 与“删除”功能无关,尤其是因为它是最终成为内存泄漏的开始。
  • 同样的ListNode *disp= new ListNode; 错误在display()
  • 当要删除的node在列表中间但恰好与头或尾节点具有相同的值时,您的remove()将从列表中删除错误的节点.这是您必须修复的另一个错误。要找出错误的原因,您需要使用调试器。您是否使用过调试器来调试您的程序,如果没有,为什么不呢?
  • @SamVarshavchik,插入到列表中的值是递增的 (1,2,3,....,n),所以我觉得不需要检查重复项,因为没有两个节点会有相同的值。我不太确定调试器,因为我真的没有使用它们的经验,但我认为这将是我学习的下一步。
  • @WhozCraig,我的理解是在函数中创建的 toDelete 只会持续函数的生命周期,因此在函数调用结束时不会有问题。不是这样吗?

标签: c++ doubly-linked-list


【解决方案1】:

我得到了一些关于其他事情的好技巧,但我发现在我的 search_value 函数中,我实际上是在使用成员函数修改头部。改为使用临时头返回节点的位置,该节点后来被正确删除。

【讨论】:

    猜你喜欢
    • 2013-10-14
    • 1970-01-01
    • 2017-04-12
    • 1970-01-01
    • 1970-01-01
    • 2019-04-03
    • 1970-01-01
    • 2015-04-15
    • 1970-01-01
    相关资源
    最近更新 更多