我无法在单循环链表中正确显示或插入元素

问题描述

我无法在单循环链表中插入和显示,它只插入第一个元素,与显示功能相同

void create() {
    struct node *temp,*p;
    temp = (struct node*)malloc(sizeof(struct node));
    printf("Enter node data :");
    scanf("%d",&(temp->data));
    temp->next = NULL;
    if(root == NULL) {
        root = p = temp;
    }
    else {
        while(p->next!=root) {      
            p->next = temp;
            p = temp;
            p->next = root;
        }
    }
}
void display() {
    struct node *temp;
    if(root == NULL) {
        printf("List is Empty\n");
    }
    else {
        temp = root;
        while(temp->next!=root) {
            printf("%d",temp->data);
            temp = temp->next;
        }
        printf("%d",temp->next);
    }
}

解决方法

create 函数的这一部分:

        while(p->next!=root) {      
            p->next = temp;
            p = temp;
            p->next = root;
        }

变量 p 未初始化,因此 p->next 是无效的取消引用。

更改如下:

        p = root;
        while(p->next!=root) {      
            p->next = temp;
            p = temp;
            p->next = root;
        }

更正未初始化的变量。代码仍然不正确,因为它丢弃了列表中现有的元素,因此列表只包含新元素。

以下将其更改为查找列表的最后一个元素,然后将新元素附加到最后一个元素:

        p = root;
        while(p->next!=root) {      
            p = p->next;
        }
        p->next = temp;

然后需要将新元素(现在是最后一个元素)链接到第一个元素来完成圆圈:

        temp->next = root;

对于链表为空的情况(即root == NULL),使root指向新节点后(即root = temp;),还需要使新节点指向自身,因为它也是第一个节点:

        temp->next = temp;

或:

        temp->next = root;

temp->next = root; 语句可以移到 if else 语句之后,因为它位于两个分支的末尾。

这是一个稍微清理过的 create 函数版本。我没有为 mallocscanf 调用的结果添加任何错误检查,因为问题和答案的主要焦点是与循环链表处理有关:

void create(void) {
    struct node *temp,*p;
    temp = (struct node*)malloc(sizeof(struct node));
    printf("Enter node data :");
    fflush(stdout);
    scanf("%d",&(temp->data));
    if(root == NULL) {
        /* list is empty so new node will become both first and last node */
        root = temp;
    }
    else {
        /* find the current last node */
        for (p = root; p->next != root; p = p->next)
            ;
        /* append the new node so it will become last */
        p->next = temp;
    }
    /* link the new,last node to the first node */
    temp->next = root;
}

现有的 display 函数现在应该可以工作了,但可以通过使用 do while 循环来简化非空情况:

void display(void) {
    struct node *temp;
    if(root == NULL) {
        printf("List is Empty\n");
    }
    else {
        temp = root;
        do {
            printf("%d ",temp->data);
            temp = temp->next;
        } while (temp!=root);
        printf("\n");
    }
}

没那么简单,还有两个printf语句(虽然最后一个可以改成putchar('\n');)。它还在换行符之前打印一个空格,因此您可能希望毕竟单独处理列表的最后一个元素:

void display(void) {
    struct node *temp;
    if(root == NULL) {
        printf("List is Empty\n");
    }
    else {
        for (temp = root; temp->next != root; temp = temp->next) {
            printf("%d ",temp->data);
        }
        printf("%d\n",temp->data);
    }
}