我用 C 语言编写了一段代码,它将创建一个链接列表。链表结构有两个字段,即 data
和 next
; data
包含整数数据,next
是一个结构体指针。
程序要求用户将数据输入到列表中。输入数据后,程序将遍历列表并检查节点中的哪些数据包含素数。如果它找到一个这样的节点,它将删除它并将下一个节点链接到前一个节点,但我收到段错误错误并且无法解决。
我把代码放在下面。 您能帮我解决一下吗,因为我不知道如何找到问题所在?
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
typedef struct node *nptr;
nptr H, h, n;
void deletetheprime(struct node**);
void display();
int prime(int);
int main() {
nptr temp1, temp;
int i, N, p;
printf("\n if list is completed enter 999\n");
for (;;) {
printf("\n enter the data \n");
scanf("%d", &i);
if (i == 999)
break;
else
if (H == NULL) {
H = h = (nptr)malloc(sizeof(struct node));
H->data = i;
H->next = NULL;
} else {
n = (nptr)malloc(sizeof(struct node));
n->data = i;
n->next = NULL;
h->next = n;
h = n;
}
}
printf("\n data before deletion\n");
display();
temp = H;
while (temp != NULL) {
N = temp->next->data;
p = prime(N);
if (p == 1) {
deletetheprime(&temp);
} else {
temp = temp->next;
}
}
printf("\n the data after deletion is\n");
display();
return 0;
}
void deletetheprime(struct node **temp2) {
nptr temp, temp1;
temp = *temp2;
temp1 = temp->next;
temp->next = temp->next->next;
free(temp1);
temp = temp->next;
}
int prime(int i) {
int j, p = 0;
for (j = 2; j <= i / 2; i++) {
if (i % j == 0) {
break;
}
}
if (j > i / 2) {
p = 1;
}
return p;
}
void display() {
nptr temp;
temp = H;
while (temp != NULL) {
printf("\n %d", temp->data);
temp = temp->next;
}
}
最佳答案
问题出在这里:
while (temp != NULL) {
N = temp->next->data;
当到达列表的最后一个元素时,temp
不是 NULL
,但 temp->next
是 temp ->next->data
具有未定义的行为。
还有其他问题:
- 您的
prime()
函数效率低下,对于0
和1
将返回1
。 - 您的
deletetheprime()
函数删除节点并更新调用者作用域中的指针,但调用者不会更新前一个节点中的链接,也不会更新H
指针如果删除的节点是第一个。 - 如果没有充分的理由使用全局变量,您应该将
H
传递给display()
并将所有变量设置为main()
中的本地变量. - 您永远不会释放已分配的对象,释放您分配的所有内容是一种很好的风格。
- 你不应该将指针隐藏在typedef后面,将
node
作为struct node
的typedef,但保持指针可见,这是一个好习惯,可以避免让读者和读者感到困惑。程序员。
要删除节点,您应该使用指针链接技巧:
for (struct node **p = &H; *p;) {
if (prime((*p)->data) {
nptr np = *p;
*p = np->next;
free(np);
} else {
p = &(*p)->next;
}
}
p
最初指向头指针 H
,随后指向前一个节点的 next
成员。当发现要删除的节点时,可用于更新头指针或前一个节点中的链接。
这是一个更正和简化的版本:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} node;
int isprime(int n) {
if (n < 2)
return 0;
if (n % 2 == 0)
return n == 2;
for (int i = 3; i * i <= n; i += 2) {
if (n % i == 0) {
return 0;
}
}
return 1;
}
void display(const node *temp) {
while (temp != NULL) {
printf(" %d", temp->data);
temp = temp->next;
}
printf("\n");
}
int main(void) {
node *H = NULL;
node **lastp = &H;
node *n;
int i;
printf("Enter values, when list is completed enter 999\n");
for (;;) {
printf("\n enter the data: ");
if (scanf("%d", &i) != 1 || i == 999)
break;
n = malloc(sizeof(*n));
if (n == NULL)
break;
n->data = i;
n->next = NULL;
*lastp = n;
lastp = &n->next;
}
printf("\n data before deletion: ");
display(H);
for (node **p = &H; *p;) {
if (isprime((*p)->data)) {
n = *p;
*p = n->next;
free(n);
} else {
p = &(*p)->next;
}
}
printf("\n the data after deletion is: ");
display(H);
/* free the list */
while (H != NULL) {
n = H;
H = n->next;
free(n);
}
return 0;
}
<小时/>
我将你的请解决它!的立场归因于你的英语水平不佳。请仔细研究本网站上的答案,以提高您的沟通能力和编程技能。
关于c - 链表 — 删除包含素数的节点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45662344/