节点不会被删除,如果它是头部



这是我的代码,至少是重要的部分。每当我运行它并试图删除head节点时,它都不会起作用(输出将是一个大负数(。它将适用于所有其他节点。

是我的代码有问题,还是你不能替换head

node* displayList(node* head) {
node* curr = head;
while (curr != NULL) {
cout << curr->data << " ";
curr = curr->next;
}
return NULL;
}
node* deleteVal(node* head, int val) {
node* cur, * prev;
if (head == NULL)
return head;

if (head->data == val) {
cur = head->next;
delete head;
head = cur;
return head;
}
cur = head;
prev = NULL;
while (cur->data != val && cur != NULL) {
prev = cur;
cur = cur->next;
}
if (cur == NULL) {
return head;
}
prev->next = cur->next;
return head;
}
int main() {
node* head1 = initNode(), * head2=initNode(), * head3 = initNode();
int val;
head1 = input();
head2 = input();
head3 = input();
conca(head1, head2, head3);
cout << "the concatated list is: ";
displayList(head1);
cout << endl<<"enter the value you want to delete: ";
cin >> val;
deleteVal(head1, val);
cout << "the new list is: ";
displayList(head1);
return 0;
}

对于启动器,while循环的条件

while (cur->data != val && cur != NULL) {
prev = cur;
cur = cur->next;
}

必须像一样更改

while ( cur != nullptr && cur->data != val) {
prev = cur;
cur = cur->next;
}

此外,您确实需要删除找到的节点,如

prev->next = cur->next;
delete cur;
return head;

而且在主要情况下,你必须将指针重新分配给像这样的头节点

head1 = deleteVal(head1, val);

有了显示的更新,功能可以按照以下方式

node* deleteVal(node* head, int val) {
node* cur, * prev;
if (head == NULL)
return head;

if (head->data == val) {
cur = head->next;
delete head;
head = cur;
return head;
}
cur = head;
prev = NULL;
while ( cur != NULL && cur->data != val ) {
prev = cur;
cur = cur->next;
}
if (cur == NULL) {
return head;
}
prev->next = cur->next;
delete cur;
return head;
}

并且在主写入

head1 = deleteVal(head1, val);

deleteVal()编码错误。

当NOT删除head节点时,如果在列表中找不到val,则while循环将显示未定义的行为。在这种情况下,在检查最后一个节点后,cur将变为NULL,然后循环将尝试再次访问cur->data,即UB。

您需要交换while语句的条件,以便在访问其data成员之前检查curNULL

while (cur != NULL && cur->data != val)

此外,如果while循环在其余节点中确实找到了val,则只需将找到的节点从列表中取消链接,但实际上并没有对该节点进行delete'链接,因此会泄漏其内存。

试试这个:

node* deleteVal(node* head, int val) {
node *cur, *prev;
if (head == NULL)
return head;

if (head->data == val) {
cur = head->next;
delete head;
return cur;
}
// we know the head node doesn't match, no need to
// test it again, so start the loop on the 2nd node...
cur = head->next;
prev = head;
while (cur != NULL && cur->data != val) {
prev = cur;
cur = cur->next;
}
if (cur != NULL) {
prev->next = cur->next;
delete cur;
}
return head;
}

话虽如此,所显示的代码还有其他问题。

CCD_ 17忽略了CCD_ 18的返回值。因此,如果head1所指向的节点实际上已从列表中删除,则main()无法知道这一点,从而最终将现在无效的node*指针传递给displayList()。因此,您需要将deleteVal()的返回值分配回head1,以反映新的列表状态:

head1 = deleteVal(head1, val);

这就是为什么按返回值返回新列表指针不是一个好的设计选择(除非在C++17及更高版本中将其标记为nodiscard(,因为它太容易被忽略。更好的设计选择是通过引用/指针传入调用方的变量,这样函数就可以在需要时直接更新调用方的参数。

此外,当调用input()时,main()正在泄漏head1head2head3节点。您正在使用initNode()创建新节点,然后重新分配指针以指向由input()创建的新节点,因此您将无法访问initNode()中的原始节点。

事实上,即使在调用deleteVal()之后,在退出程序之前也不会释放任何剩余的节点。虽然操作系统确实会在程序退出时回收所有使用过的内存,但最好明确释放您分配的任何内存。

此外,您的deleteVal()是不必要的复杂,它可以大大简化。

此外,displayList()根本没有充分的理由返回任何内容。

话虽如此,不如试试这样的东西:

void displayList(node* head) {
node* curr = head;
while (curr != NULL) {
cout << curr->data << " ";
curr = curr->next;
}
cout << endl;
}
void deleteVal(node* &head, int val) {
node *cur = head, **prev = &head;
while (cur != NULL) {
if (cur->data == val) {
*prev = cur->next;
delete cur;
return;
}
prev = &(cur->next);
cur = cur->next;
}
}
void deleteList(node* &head) {
node *cur = head, *next;
head = NULL;
while (cur != NULL) {
next = cur->next;
delete cur;
cur = next;
}
}
int input() { // <-- return int, not node* !
...
return ...; // <-- just the user's entered value, not a node wrapping the value
}
int main() {
node* head1 = initNode(), *head2 = initNode(), *head3 = initNode();
head1->data = input();
head2->data = input();
head3->data = input();
conca(head1, head2, head3);
cout << "the concatenated list is: ";
displayList(head1);
cout << "enter the value you want to delete: ";
int val;
cin >> val;
deleteVal(head1, val);
cout << "the new list is: ";
displayList(head1);
deleteList(head1);
return 0;
}

相关内容

最新更新