【问题标题】:Linked list — deletion of nodes which contain prime numbers [closed]链表——删除包含素数的节点 [关闭]
【发布时间】:2017-08-13 16:10:50
【问题描述】:

我用 C 语言编写了一个代码,它将创建一个链表。链表structre有两个字段,分别是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;
    }
}

【问题讨论】:

  • 使用调试器逐行执行代码时,您观察到了什么?
  • 请解决它”:SO不是调试服务。使用符号编译,在调试器中运行代码以逐行跟踪程序,检查相关变量的值以了解真正发生了什么。如果出现具体问题,请随时返回此处。

标签: c struct linked-list


【解决方案1】:

问题出在这里:

while (temp != NULL) {
    N = temp->next->data;

当您到达列表的最后一个元素时,temp 不是NULL,但temp-&gt;next 是所以temp-&gt;next-&gt;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;
}

我会将你的请解决它!的立场归因于你对英语的糟糕掌握。请通过仔细研究本网站上的答案来学习提高您的沟通能力和编程技能。

【讨论】:

    【解决方案2】:

    问题出现在这里,在 main

    while(temp!=NULL)
    {
        N=temp->next->data;
    ...
    

    您正在检查temp是否不是NULL,这是正确的,而是访问next节点的数据,可以NULL,并且 strong> 成为列表末尾附近的NULL,这会导致未定义的行为。

    只需修改为

    while(temp!=NULL)
    {
        N=temp->data;
    ...
    

    您确定 temp 不是 NULL 并且您不会在此处收到分段错误。它会起作用的。

    或者如果你需要访问temp-&gt;next-&gt;next节点的数据,你必须检查next-&gt;next是否也不是NULL

    while(temp!=NULL)
    {
        if (temp->next->next != NULL)
        {
            N=temp->next->data;
        }
        else // temp->next->next is NULL so you can't access the data
    ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-01
      • 1970-01-01
      • 2022-01-05
      • 2021-02-13
      • 2019-06-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多