C++ 从链表中删除给定整数的倍数

c++ remove multiples of a given integer from a linked list

本文关键字:整数 链表 删除 C++      更新时间:2023-10-16

对不起我的无知,但我在这里和C++都是新手。我正在研究链表,有一个练习,我必须编写一个函数来输入整数和整数 n 的列表。该函数必须从列表中删除所有 n 的倍数节点并返回列表。我认为我做对了,但我的代码没有输出任何东西。有人可以解释我为什么吗?谢谢大家!

#include <iostream>
using namespace std;
struct list{
int val;
list* next;
};
typedef list* ptr_list;
ptr_list new_node(ptr_list old_node, int value);
ptr_list remove_mult(ptr_list head, int n);
void print_list(ptr_list head);
int main() {
ptr_list head, p1, p2, p3;
head = new list;
head->val = 1;
p1 = new_node(head, 2);
p2 = new_node(p1, 3);
p3 = new_node(p2, 4);
p3->next = NULL;
remove_mult(head, 2);
print_list(head);
return(0);
}
ptr_list new_node(ptr_list old_node, int value)
{
old_node->next = new list;
old_node->next->val = value;
return old_node->next;
}

ptr_list remove_mult(ptr_list head, int n){
ptr_list prev, curr;
prev = head;
curr = head->next;
while(curr->next != NULL){
if((head->val % n) == 0){
head = head->next;
curr = curr->next;
}
else if((curr->val % n) == 0){
ptr_list tmp;
tmp = prev->next;
prev->next = tmp->next;
delete tmp;
}
prev = curr;
curr = curr->next;
}
if((curr->val % n) == 0){
prev->next = NULL;
delete curr;
}
return(head);
}
void print_list(ptr_list head){
while ( head != NULL ){
cout << head->val << " ";
head = head->next;
}
}

这种方法

ptr_list head, p1, p2, p3;
head = new list;
head->val = 1;
p1 = new_node(head, 2);
p2 = new_node(p1, 3);
p3 = new_node(p2, 4);
p3->next = NULL;
//...
ptr_list new_node(ptr_list old_node, int value)
{
old_node->next = new list;
old_node->next->val = value;
return old_node->next;
}

不好,因为它不安全。例如,用户可以向函数传递空指针。或者,传递的指针旁边的数据成员可以指向有效节点。在这种情况下,它将在函数中被覆盖,并且会出现内存泄漏。或者用户在退出函数后忘记将最后一个节点旁边的数据成员设置为nullptr

函数remove_mult也无效。例如,传递的指针通常可以等于nullptr。在这种情况下,函数具有未定义的行为。

ptr_list remove_mult(ptr_list head, int n){
ptr_list prev, curr;
prev = head;
curr = head->next;
//...

该函数还存在内存泄漏,因为您忘记删除此 if 语句中的头节点

if((head->val % n) == 0){
head = head->next;
curr = curr->next;
}

在此其他语句中

else if((curr->val % n) == 0){
ptr_list tmp;
tmp = prev->next;
prev->next = tmp->next;
delete tmp;
}

您忘记设置变量的新值curr

在 if-else 语句之后

prev = curr;
curr = curr->next;

您正在再次设置prev。这再次导致未定义的行为,例如删除当前节点时。

下面是一个演示程序,演示如何实现列表的功能。

#include <iostream>
struct list
{
int val;
list* next;
};
typedef list* ptr_list;
ptr_list remove_mult(ptr_list head, int n )
{
ptr_list curr = head;
ptr_list prev = nullptr;
while ( curr != nullptr )
{
if ( curr->val % n == 0 )
{
ptr_list tmp = curr;
if ( prev == nullptr )
{
head = curr = curr->next;
}
else
{
curr = prev->next = curr->next;
}
delete tmp;
}
else
{
prev = curr;
curr = curr->next;
}
}
return head;
}
void print_list( ptr_list head )
{
for ( ; head != nullptr; head = head->next )
{
std::cout << head->val << ' ';
}
}
ptr_list append_list( ptr_list tail, int val )
{
if ( tail == nullptr )
{
tail = new list { val, nullptr };
}
else
{
while ( tail->next != nullptr )
{
tail = tail->next;
}
tail->next = new list { val, nullptr };
tail = tail->next;
}
return tail;
}
int main() 
{
ptr_list head = nullptr;
const int N = 10;
ptr_list tail = nullptr;
for ( int i = 0; i < N; i++ )
{
if ( head == nullptr )
{
head = append_list( head, i );
tail = head;
}
else
{
tail = append_list( tail, i );
}
}
print_list( head );
std::cout << 'n';
head = remove_mult( head, 2 );
print_list( head );
std::cout << 'n';
return 0;
}

它的输出是

0 1 2 3 4 5 6 7 8 9 
1 3 5 7 9