c - 链表 — 删除包含素数的节点

标签 c struct linked-list

我用 C 语言编写了一段代码,它将创建一个链接列表。链表结构有两个字段,即 datanextdata 包含整数数据,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->nexttemp ->next->data 具有未定义的行为。

还有其他问题:

  • 您的 prime() 函数效率低下,对于 01 将返回 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/

相关文章:

c - 我应该使用位域来映射传入的串行数据吗?

java - 使用 native 语言为 C 或 C++ 的 JNI 接口(interface)在 Java 中实现 USB 通信是个好主意吗?

c - 如何将结构映射为共享匿名内存?

c - 不知道为什么我在这里遇到段错误

c - C中的链表结构与读取txt

C - mkfifo , ls - 不要停止

c++ - 如何通过 IO 时序测量找到 L1 缓存线大小的大小?

c - 使用 GNU 程序集访问指向结构的 *next 指针

C 移位插入链表

c - 尝试使用链接列表时出现无限循环