链接列表 - 删除包含素数的节点

时间:2017-08-13 16:10:51

标签: c struct linked-list

我用C语言编写了一个代码,用于创建链接列表。链表结构有两个字段,即datanext; 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;
    }
}

2 个答案:

答案 0 :(得分:1)

问题出现在主

temp

您正在检查NULL是否不是next,这是正确的,但访问NULL节点的数据,可以NULL 在列表末尾附近while(temp!=NULL) { N=temp->data; ... ,这会导致未定义的行为。

只需将其修改为

即可
NULL

你确定temp不是temp->next->next,你在这里不会得到分段错误。而且它会起作用。

或者,如果您需要访问next->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 ...

react-native run-android

答案 1 :(得分:1)

问题在于:

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

当您到达列表的最后一个元素时,temp不是NULL,但temp->nexttemp->next->data具有未定义的行为。

还有其他问题:

  • 您的prime()函数效率低下,将10返回1
  • you 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;
}

我将把你的归结为你解决它!对你糟糕的英语语言的立场。请通过仔细研究本网站的答案,学习如何改善沟通和编程技巧。