删除链表 C++ 中的特定节点
Posted
技术标签:
【中文标题】删除链表 C++ 中的特定节点【英文标题】:Deleting a specific node in Linked List C++ 【发布时间】:2021-07-22 15:33:38 【问题描述】:我有一个保存学生数据的学生类,然后我的节点由这个学生类的一个对象组成。
我想删除分数低于 550 的学生。我的学生名单很长,但程序会在找出第一个分数低于 550 的人后删除所有数据。
这是我的链接列表:
class LinkList // Linked List
struct Node // structure for Node containing Object of Student class
Student info;
Node* link;
;
Node* head;
public:
LinkList() // default constructor
head = NULL;
void CreateEntry();
void print();
void Delete();
;
这是我的数据示例:(一行是每个节点)
S# Roll_no Name marks
1 0777 Sherlock Holmes 777
2 0789 John Watson 734
3 0860 James moriarty 390
4 0884 Irene Adler 732
5 1003 Mycroft Holmes 410
6 1004 Lord Blackwood 632
这是我的删除功能:
Node* ptr = head;
int n;
while(ptr->link != NULL) // traversing to last element
n = ptr->info.GetSerialNo(); // where n becomes the total number of elements
ptr = ptr->link;
Node* temp = head;
for(int i=0; i<n; i++)
if(temp->info.Getmarks() < 550) // Getmarks returns the marks
if(temp != NULL && temp->link != NULL)
Node* nodeToDelete = temp->link;
temp->link = temp->link->link;
delete nodeToDelete;
else
temp = temp->link;
我得到的输出是:
S# Roll_no Name marks
1 0777 Sherlock Holmes 777
2 0789 John Watson 734
【问题讨论】:
在调试器下运行你的程序,在Node* nodeToDelete = temp->link;
所在的行设置一个断点。记下temp
变量的内容。现在一步一步直到你到达下一次迭代的开始。 temp
现在的价值是多少?发生什么了?更重要的是,您预计会发生什么,为什么没有呢?
无关:如果列表为空,while(ptr->link != NULL)
会死得很惨,因为ptr
将是NULL
。修复它,您会发现该功能仅在您第一次删除节点时才能正常工作。之后,序列号可能无法准确表示列表中的节点数。也就是说,为什么不在那个初始循环中进行搜索和删除?搜索直到列表中没有更多节点。这将永远有效。
不相关:您的 temp != NULL
检查没有用(您已经访问了上面的 temp )并且您的编译器可能删除了检查。如果您的警告级别足够高,它应该会警告您。
无关:您将序列号分配给n
以获取列表的长度,但您允许删除。这可能意味着您的最终n
大于或小于列表的长度。为什么还要使用n
?您可以将 for
循环重写为 for(Node *ptr = head; ptr != NULL; ptr = ptr -> link)
,它会为您完成所有检查
完全无关:Sherlock 到底是怎么比他的哥哥更聪明的?
【参考方案1】:
我想删除分数低于 550 的学生
您的Delete()
比完成该任务所需的复杂得多。而且,它也有一些逻辑错误。
试试类似的方法:
void LinkList::Delete()
Node* ptr = head;
Node* previous = NULL;
while (ptr != NULL)
Node* nextNode = ptr->link;
if (ptr->info.Getmarks() < 550)
if (previous)
previous->link = nextNode;
if (head == ptr)
head = nextNode;
delete ptr;
else
previous = ptr;
ptr = nextNode;
或者:
void LinkList::Delete()
Node* ptr = head;
Node** previous = &head;
while (ptr != NULL)
Node* nextNode = ptr->link;
if (ptr->info.Getmarks() < 550)
*previous = nextNode;
delete ptr;
else
previous = &(ptr->next);
ptr = nextNode;
话虽如此,你真的应该使用标准的std::list
容器而不是自己制作链表,那么你可以这样做:
#include <list>
class LinkList // Linked List
std::list<Student> students;
public:
LinkList() = default; // default constructor
...
void Delete();
;
#include <algorithm>
void LinkList::Delete()
students.erase(
std::remove_if(students.begin(), students.end(),
[](Student &s) return s.Getmarks() < 550;
),
students.end()
);
【讨论】:
以上是关于删除链表 C++ 中的特定节点的主要内容,如果未能解决你的问题,请参考以下文章