这是我编写的删除函数,用于在需要时从链接列表中删除一些节点。
使用下面的函数,当我尝试删除链接列表的第一个元素(名为head)时,当我尝试打印链接列表(使用打印功能)并且程序崩溃时,我收到运行时错误。我知道这可能是因为没有创建新的头节点。但我不知道如何解决这个问题。这可能很简单,但无法弄清楚。你可以帮忙:))
这是删除功能:
void deleteName(someStruct * &head, string name)
{
someStruct * ptr = head;
someStruct * previous;
if(head == NULL)
{
cout << "empty";
}
else if(head->name == name)
{
ptr = head;
head = head->next;
delete head;
}
else
{
while (ptr -> name != name)
{
previous = ptr;
ptr = ptr->next;
}
previous->next = ptr->next;
delete ptr;
}
}
这是打印功能:
void Print(someStruct * head)
{
someStruct * pointer = head;
//List is empty
if(head == NULL)
{
cout << "List is empty" << endl;
}
else
{
while(pointer != NULL)
{
cout << pointer->name;
cout << pointer->points << endl;
pointer = pointer->next;
}
}
}
答案 0 :(得分:1)
else if(head->name == name)
{
ptr = head;
head = head->next;
delete head;
}
此:
head
的旧值保存到ptr
,这是正确的head
,这也是正确的完全忽略ptr
,其中包含您要删除的旧节点,而是删除当前列表头,让inout参数head
指向已删除的节点。
此位不正确。
只需将delete head
更改为delete ptr
。
注意以备将来参考:良好的结构方法是使用不需要删除的本地sentinel节点。这将删除head
的特殊情况(通过添加永远不会删除临时头的不变量)并简化代码。
void deleteName(someStruct * &head, string name)
{
if(!head) {
cout << "empty";
return;
}
someStruct tmphead;
tmphead.next = head;
for (someStruct *prev = &tmphead; prev->next; prev = prev->next) {
if (prev->next->name == name) {
auto todelete = prev->next;
prev->next = todelete->next;
delete todelete;
// if there can be only one match, just bail out
break;
// otherwise, if there can be many, go round again
// but remember to check whether prev->next is null
// if (!prev->next) break;
}
}
head = tmphead.next;
}
如果someStruct
太大或太复杂而无法像这样使用临时头,则可以使用临时本地头指针执行相同操作,并使prev
成为指向指针的指针。 / p>
答案 1 :(得分:1)
delete head
块中的else if
是问题所在。
将块更改为:
else if(head->name == name) {
//ptr = head; You don't have to. You already have initialized ptr with head
head = head->next;
delete ptr; //Delete prt not head, head is now the next node which you assigned in previous line
}
答案 2 :(得分:1)
else if(head->name == name){
ptr = head;
head = head -> next;
delete ptr; // change to this statement n you're good to go
}