【问题标题】:Linked List inserting trouble链表插入问题
【发布时间】:2013-09-24 06:02:36
【问题描述】:

我在链接列表中插入项目时遇到问题。所有元素最终都具有最后插入的相同 *data 内容。程序编译成功。我使用 gcc 和 gdb。 我是编码新手,所以如果您在我的编程风格中看到任何麻烦,请提及。

typedef struct Node{
    void* data;
    struct Node* next;
} *node;

node allocate(){
    node current = malloc(sizeof(struct Node));
    current->data = NULL;
    current->next = NULL;
    return current;
}


void insert(node *head, void *data){
    // if head has no data then set the data on head and return
    if(((*head)->data == NULL)&&((*head)->next == NULL)){
        (*head)->data = data;
        return;
    }

    node newHead = allocate();
    newHead->data = data;
    newHead->next = *head;
    *head = newHead;
    //printf("Node Data : %d\tNext Node Data : %d",
        //*(int *)((*head)->data), *(int *)((*head)->data));
}

int main(int argc, char *argv[]){
    node head = allocate();
    int count = inputSequence(&head);
    int *aod = calloc((size_t) count, sizeof(int));
    generateAOD(head, aod);
    if(checkJolly(aod, count) == TRUE)
        printf("Jolly\n");
    else
        printf("Not Jolly\n");

    return 0;
}

int inputSequence(node *input){
    int *num = malloc(sizeof(int));
    int count = 0;

    while((scanf("%d", num) != EOF)){
        insert(input, (void *)num);
        count++;
    }
    traverse(*input, fn);
    return count;
}

【问题讨论】:

  • 你有main函数的代码吗?
  • 是的。我已经将主要功能和链接列表模块实际上放在不同的文件中
  • @lc2817 .. 我可以在 stackoverflow 上上传文件还是可以通过电子邮件发送它们?
  • 我在顶部看到的一个问题是,在确定列表是否为“空”时,您正在使用data 成员状态为非空的预分配头指针。绝对没有理由这样做。头指针本身(null vs. not-null)是“空”状态的更清晰的指示器。第二。您永远不会在 insert() 函数中分配新节点,因此当然不会发生“插入”。
  • 在您的其他代码下方添加主文件。谢谢

标签: c coding-style singly-linked-list


【解决方案1】:

您的插入逻辑不存在。通过尝试以您正在使用的方式管理链接列表,您实际上使您的生活变得更加艰难。

头指针本身应该指示列表是否为空。如果为NULL,则为空。如果不是,则有数据。相应地编码插入逻辑。

而你的inputSequence 完全崩溃了。它只分配一个数据点,然后为每个插入使用相同的数据分配。 每个插入都需要一个。

首先,更改allocate() 以接受正在插入的数据。它将使剩余的代码不那么混乱:

node allocate(void *data)
{
    node current = malloc(sizeof(*current));
    current->data = data;
    current->next = NULL;
    return current;
}

其次,根据需要分配一个新节点来插入。

void insert(node *head, void *data)
{
    node p = allocate(data);
    p->next = *head;
    *head = p;
}

接下来,修复inputSequence() 为每个条目正确分配内存:

int inputSequence(node *input)
{
    int count = 0;
    int num = 0;

    // note: check for number of params *successfully* parsed.
    //  if it isn't 1, its time to leave the loop.
    while(scanf("%d", &num) == 1)
    {
        int *data = malloc(sizeof(num));
        *data = num;
        insert(input, data);
        ++count;
    }
    return count;
}

最后,确保 main() 中的头指针最初为 NULL。

int main(int argc, char *argv[])
{
    node head = NULL;

    // load linked list
    inputSequence(&head);

    // ... the rest of your code....;

    return 0;
}

根据上述情况,“我的列表是否为空”的逻辑答案很简单if (!head) 此外,这使得遍历之类的事情变得微不足道。

void traverse(node ptr, void (*pfn)(void *))
{
    while (ptr)
    {
        pfn(ptr->data);
        ptr = ptr->next;
    }
}

释放列表同样简单:

void destroy(node *head)
{
    while (*head)
    {
        node p = *head;
        *head = p->next;
        free(p->data);
        free(p);
    }
}

【讨论】:

  • @user2794538 没问题。我只是希望这是有道理的。
【解决方案2】:
   typedef struct Node{
         void* data; // Make it as int or any other data type
         struct Node* next;
   } *node;

在函数 inputSequence() 中,您在一开始就为 num 分配内存,并在每次添加节点时使 node->data 指向该内存。因此,链表的每个节点的数据指针都指向相同的内存位置,因此包含相同的值。

如果您仍想将数据作为 void 指针继续,请为 while 循环的每次迭代分配 num 并将其传递给 insert 函数。

    while((scanf("%d", num) != EOF)){
        num = malloc(sizeof(int);
        insert(input, (void *)num);
        count++;
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-07
    相关资源
    最近更新 更多