单链表按顺序插入和删除值

Posted

技术标签:

【中文标题】单链表按顺序插入和删除值【英文标题】:Singly Linked List inserting and deleting value in order 【发布时间】:2021-06-15 22:11:57 【问题描述】:

我的任务是创建函数来添加和删除链表中的节点,给定输入数据作为 int 和要调用的函数的 char。我不确定我做错了什么。我得到的唯一错误是:退出并返回代码 -11 (SIGSEGV)。还有一个编译器方法:main.cpp:在函数‘void listInsertValue(ListNode*&, ListNode*&, int)’中: main.cpp:111:23:警告:“toGoAfter”可能在此函数中未初始化使用 [-Wmaybe-uninitialized] 111 | toGoAfter->next = head;

感谢任何帮助。谢谢!

#include <iostream>
using namespace std;

struct ListNode

    int data;
    ListNode* next;
;

void listRemoveAfter(ListNode*&, ListNode*&, ListNode*);
void listPrepend(ListNode*&, ListNode*&, ListNode*&);
void listDeleteValue(ListNode*&, ListNode*&, int);
void listInsertValue(ListNode*&, ListNode*&, int);
void listInsertAfter(ListNode*&, ListNode*&, ListNode*, ListNode*);

int main()

    
    ListNode *head = nullptr, *tail = nullptr;
    ListNode *temp;
   char choice;
   int val;

   //Write a main like you did in the previous lab
   char command;
   int number;
   
   cin >> command;
   while(command != 'Q')
   
        if(command == 'I')
        
            cin >> number;
            listInsertValue(head,tail,number);
        
        else
        
            cin >> number;
            listDeleteValue(head,tail,number);
        
        
      cin >> command;
   
   ListNode* current;
   current = head;
    while (current != nullptr)
    
        cout << current->data << " ";
        current = current->next;
    
    cout << endl;
    return 0;



//From previous lab - already complete
void listPrepend(ListNode*& h, ListNode*& t, ListNode*& n)

    if (h == nullptr)
    
        h = n;
        t = n;
    
    else
    
        n->next = h;
        h = n;
    


//From book, write yourself using the book code in 17.6 as a starting point
void listInsertAfter(ListNode*&head, ListNode*&tail, ListNode* curNode, ListNode* newNode)

   if (head->next == nullptr) 
    
      head= newNode;
      tail = newNode;
   
   else if (curNode->next == tail) 
    
      tail->next = newNode;
      tail = newNode;
   
   else 
   
      newNode->next = curNode;
      curNode->next = newNode;
   



//This function is mostly written, but you will need to add some code near the TODOs to complete the algorithm from the slides
void listInsertValue(ListNode*& head, ListNode*& tail, int val)

    ListNode* toGoAfter, *newNode;

   //TODO - create a new ListNode (newNode) with a data value of val (3 lines of code)
   newNode = new ListNode;
   newNode->data = val;
   newNode->next = nullptr;
    //TODO - check whether the list is empty in the if condition
    if (head == nullptr)
    
        listInsertAfter(head, tail, nullptr, newNode);
    
    //TODO - use the else if to check whether the the value passed in is smaller than the value in the head
    else if (head->data > val)  //need to add to beginning of the list
    
        listPrepend(head, tail, newNode);
    
    else //need to add somewhere else in the list
    
       //TODO - set toGoAfter to point to the head
      toGoAfter->next = head;
      //loop to find the location to insert the value
        while (toGoAfter->next != nullptr && toGoAfter->next->data < val)
        
           //TODO - set toGoAfter to point to the node after toGoAfter, like is done in traversals
           toGoAfter = toGoAfter->next;
        

      //We have found the location, so we can insert
        listInsertAfter(head, tail, toGoAfter, newNode);

    


//modify
void listDeleteValue(ListNode* &head, ListNode*& tail, int val)

    ListNode *temp;

   //TODO - check if list is not empty in if condition
    if (head->next == nullptr)
    
       // TODO - check if value of head matches val passed in
        if (head->data == val)
            listRemoveAfter(head, tail, nullptr);
    
        else
        
           //loop searches for value to delete in node following temp
           //TODO - set temp to point to the head
           temp->next = head;
            while (temp->next != nullptr && temp->next->data != val)
            
               //TODO - set temp to point to the node after temp, like is done in traversals
               temp = temp->next;
            

         //TODO - make sure a node exists after temp, meaning the value to delete was found
            if (temp->next != nullptr)
                listRemoveAfter(head, tail, temp);
        
    


//From book, write yourself using the book code in 17.7 as a starting point
//Also add to the book's code, the code to delete nodes from memory
void listRemoveAfter(ListNode* & head, ListNode*& tail, ListNode* curNode) 

    ListNode *sucNode, *toDelete;
    
     if (curNode->next == nullptr && head->next != nullptr) 
     
       sucNode = head->next;
      head->next = sucNode;

      if (sucNode->next == nullptr) 
       // Removed last item
         tail->next = nullptr;
         toDelete = head;
      
   
   else if (curNode->next != nullptr)
   
      sucNode = curNode->next->next;
      curNode->next = sucNode;

      if (sucNode-> next == nullptr)
       // Removed tail
         tail->next = curNode;
         toDelete = curNode->next;
      
      
   

    delete toDelete;  //needed after the if/else if to remove the deleted node from memory


【问题讨论】:

建议 -- 摆脱cin 语句并使用导致问题的已知数据直接调用函数。这允许您(和其他人)直接运行代码,而无需在每次运行程序时都输入。 您的第一个问题确实出在listInsertValue 函数中。在您的第一次插入中,您调用listInsertAfter 并以head 作为第一个参数......但是您刚刚检查了head == nullptr 所以....当您尝试检查if(head-&gt;next == nullptr) 时,BOOM :) 另一个问题等待着您。祝你好运:) 我认为您可能对toGoAfter-&gt;next = head; 有疑问。您从未将toGoAfter 设置为任何值,但您仍在尝试将其设置为next 值。我认为在那一行中你只想要toGoAfter = head; 以便toGoAfter 它自己 指向头部。 链接列表是一个非常重要的概念,您需要确保自己非常了解。当您为此苦苦挣扎时,我将向您推荐谷歌“链表教程”,然后找到一个看起来不错的。如果您以这种方式学得很好,最近 YouTube 上有一些很棒的教程。花时间去真正理解是值得的。 【参考方案1】:

在大多数情况下,当列表中没有元素时,您不会处理这种情况。插入句柄4用例时

    head==nullptr => head =newNode; head->数据> val 尾部->数据其他情况:插入中间

一般错误:访问ptr-> next,当ptr为nullptr时

一般来说,您希望使用调试器,并且对内存 0x0 (nullptr) 的任何访问都将开始解决您的问题。即 head 是 0x0 并且您正在执行 head->data ==val

之类的操作

【讨论】:

以上是关于单链表按顺序插入和删除值的主要内容,如果未能解决你的问题,请参考以下文章

数据结构之单链表

单链表与顺序表的对比

算法专区博文汇总

单链表 - 插入和删除操作

数据结构之单链表

数据结构之单链表