1

我仍在学习链表,并一直在尝试创建一种插入链表的方法。

我只想知道这是否是正确的插入方式?另外,我将如何打印整个链表,所以它会打印类似abc.

这是我所拥有的:

struct node {
   char value;
   struct node *next;
};

typedef struct node item;

void main() {
    InsertChar('a');
    InsertChar('b');
    InsertChar('c');
}

void InsertChar(char s) {
    item *curr, *head;

    head = NULL;

    curr = (item *)malloc(sizeof(item));
    curr->value = s;
    curr->next = head;
    head = curr;

    while(curr) {
        printf("%c\n", curr->value);
        curr = curr->next;
    }
}
4

2 回答 2

3

首先,您的函数InsertChar会覆盖head每次 ( head = curr) 的值,因此您最终会得到一个包含一项的列表。

您需要声明将存储的东西head

struct list
{
    struct node *head;
};

现在您可以list通过每个node.

void PrintList(struct list* list)
{
    struct node *curr = list->head;

    while (curr != NULL)
    {
        printf("%c\n", curr->value);
        curr = curr->next;
    }
}

现在您需要修改InsertChar以使列表中的最后一项(您将如何找到它?)指向您的新项。我会把它留给你:)

于 2013-11-03T04:48:12.660 回答
0

As you may have noticed, you have no means to access the list (if there was any) from outside InsertChar(). You don't use a global variable, nor do you input or output it.

A better implementation:

item * InsertChar(item ** phead, char s) {
    item * curr;

    // First, allocate a new item and fill it.
    curr = malloc(sizeof(item)); // no need to cast here
    if (curr) { // only if malloc() succeeds
        curr->value = s;
        curr->next = *phead;
        *phead = curr;
    }
    return curr;
}

// InsertChar() is only supposed to insert, not to print.
void PrintList(item * head) {
    item * curr = head;   
    while(curr) {
        printf("%c", curr->value); // omit the line break as you want abc
        curr = curr->next;
    }
    printf("\n"); // now the line break
    return;
    // alternative implementation for while loop:
    for(curr=head; curr; curr=curr->next) {
        printf("%c\n", curr->value);
    }
}

void FreeList(item * head) {
    item * curr = head;   
    while(curr) {
        item * next = curr->next; // read it out before freeing.
        free(curr);
        curr = next;
    }
}

so that you can do now

int main() {
    item * list = NULL; // empty for now, no contents.
    char success = 1;
    success = success && InsertChar(&list, 'a');
    success = success && InsertChar(&list, 'b');
    success = success && InsertChar(&list, 'c');
    if (!success) {
        printf("Oops?");
        FreeList(list);
        return 1;
    }
    PrintList(list);
    FreeList(list); // clean up.
}

Oops? I didn't test it, but it seems to me that it prints "cba". Why does it so? Well, InsertChar() puts everything to the start.

How to get around of this?

Either we can create an AppendChar() function. But this bears the danger that we into the trap of Schlemiel the Painter's algorithm: to start searching for the right place always from the start. Thus, I'll point out another approach:

int main() {
    item * list = NULL; // empty for now, no contents.
    item * cursor = InsertChar(&list, 'a');
    if (!cursor) goto error;
    // cursor now contains our first entry.
    // We put the next one to cursor->next:
    cursor = InsertChar(&cursor->next, 'b');
    if (!cursor) goto error;
    cursor = InsertChar(&cursor->next, 'c');
    if (!cursor) goto error;
    PrintList(list);
    FreeList(list); // clean up.
    return 0;
  error:
    printf("Oops?");
    FreeList(list);
    return 1;
}

I am not sure if I am right (didn't test it), but this should be the way to go.

If you are one of these who were taught that goto is evil under all circumstances, feel free to implement the error handling in a different way.

于 2013-11-03T18:36:03.320 回答