首页 > 解决方案 > 链表中的顺序有时有效,有时无效。很奇怪

问题描述

此代码只是尝试创建字符的链接列表。奇怪的是,有时它有效,有时则无效。我真的不知道为什么。

#include <stdio.h>
#include <stdlib.h>


struct mychar {
    char value;
    struct mychar *nextPtr;
};

typedef struct mychar Mychar;


void insert(Mychar **, char );
void printlist(Mychar *);

int main(){
    Mychar *startPtr = NULL;

    while (1) {
        char letter;
        printf("\nScrivi il carattere da aggiungere: ");
        scanf("\n%c", &letter);

        insert(&startPtr, letter);

        printlist(startPtr);
    }
}


void insert(Mychar **sPtr, char newvalue){
    Mychar *newnodePtr = calloc(1, sizeof(Mychar));
    if (!newnodePtr){
        printf("\n\nError in memory allocation.\n\n");
        return;
    }
    newnodePtr->value = newvalue;

    Mychar *previousPtr = NULL;
    Mychar *currentPtr = *sPtr;

    while ( currentPtr!=NULL && newvalue > (currentPtr->value) ){
        previousPtr = currentPtr;
        currentPtr = currentPtr->nextPtr;
    }

    if (previousPtr==NULL){
        newnodePtr->nextPtr = NULL;
        *sPtr = newnodePtr;
    } else {
        previousPtr->nextPtr = newnodePtr;
        newnodePtr->nextPtr = currentPtr;
    }
}

void printlist(Mychar *sPtr){
    Mychar *currentPtr = sPtr;
    while (currentPtr!=NULL){
        printf("%c", currentPtr->value);
        currentPtr = currentPtr->nextPtr;
    }
}

Output1(似乎不起作用,当添加一个小写字母时,所有节点都消失了):

Write the char to add: a
a
Write the char to add: b
ab
Write the char to add: c
abc
Write the char to add: z
abcz
Write the char to add: a
a
Write the char to add: b
ab
Write the char to add: z
abz
Write the char to add: a
a
Write the char to add: ^C

输出 2(似乎有效):

Write the char to add: A
A
Write the char to add: B
AB
Write the char to add: C
ABC
Write the char to add: a
ABCa
Write the char to add: z
ABCaz
Write the char to add: a
ABCaaz
Write the char to add: b
ABCaabz
Write the char to add: Z
ABCZaabz
Write the char to add: ^C

另外,我想释放退出程序时创建的所有节点(例如使用 Ctrl+c)..

如何释放所有动态分配的节点?

标签: cpointersdata-structuresstructlinked-list

解决方案


nextPtr在节点将成为新列表头的情况下,您的代码无法正确连接新节点的成员。您可以通过执行以下操作来解决此问题,并显着简化插入:

void insert(Mychar **sPtr, char newvalue)
{
    while (*sPtr && (*sPtr)->value < newvalue)
        sPtr = &(*sPtr)->nextPtr;

    Mychar *newPtr = malloc(sizeof *newPtr);
    if (!newPtr)
    {
        perror("Failed to allocate new node");
        return;
    }
    newPtr->value = newvalue;
    newPtr->nextPtr = *sPtr;
    *sPtr = newPtr;
}

这种技术具有隐式处理所有插入情况的额外好处,包括头部、中间和尾部位置。

既然你问过如何释放列表,上面的代码应该会给你一些见解,但它可能看起来像这样:

void freelist(Mychar **sPtr)
{
    while (*sPtr)
    {
        Mychar *tmp = *sPtr;
        *sPtr = tmp->nextPtr;
        free(tmp);
    }
}

推荐阅读