最后是C链表插入节点而不替换上一节点

时间:2015-08-12 12:40:36

标签: c singly-linked-list

我在C中的链接列表的插入方法遇到了一些问题。看起来我所做的每个插入只替换了前一个插入。所以最后列表总是只包含一个单元格。我认为问题始于“insertToEndList”函数。你有没有看到它失败的原因?

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

typedef struct listNode{
    int* dataPtr;
    struct listNode* next;
}ListNode;

typedef struct list
{
    ListNode* head;
    ListNode* tail;
}List;

void deleteFromBeginnigOfList (List *list);
void deallocateListCell (ListNode *cell);
void freeList (List *list);
void printList (List *list);
void insertDataToBeginningList (List *list, int num);
void addToBeginningList (List *list, ListNode *cell);
List merge (List list1, List list2);
ListNode *createCell (int num);
void addToEmtyList(List *list, ListNode *cell);
void addToEndList(List *list, ListNode *cell);
void insertDataToEndList(List *list, int num);
void makeEmptyList(List *list);
List getList();
void main()
{

    List lst1, lst2, mergedList;

    lst1 = getList();
    lst2 = getList();
    mergedList = merge(lst1,lst2);

    printf("Merged list:\n");
    printList(&mergedList);

    freeList(&lst1);
    freeList(&lst2);
    freeList(&mergedList);

}

List getList()
{
    List res;
    int size, num, i;

    makeEmptyList(&res);

    printf("Please enter the number of items to be entered:\n");
    scanf("%d", &size);

    printf("Please enter the numbers:\n");
    for(i = 0; i < size; i++)
    {
        scanf("%d", &num);
        insertDataToEndList(&res, num);
    }

    return res;

}
void makeEmptyList(List *list){
    list->head=list->tail=NULL;
}
void insertDataToEndList(List *list, int num){

    ListNode *cell_to_add= createCell (num);
    if (list->head==NULL)
        addToEmtyList(list, cell_to_add);
    else
        addToEndList(list, cell_to_add);
}
ListNode *createCell (int num){
    ListNode *cell=(ListNode*)malloc(sizeof(ListNode));
    if (!cell)
    {
        printf("memory allocation failed\n");
        exit(1);
    }
    cell->dataPtr=&num;
    cell->next=NULL;

    return cell;
}
void addToEmtyList(List *list, ListNode *cell){
    list->head=list->tail=cell;
}
void addToEndList(List *list, ListNode *cell){
    list->tail->next=cell;
    list->tail=cell;
}
List merge (List list1, List list2){
    List merge_res; 
    ListNode *curr_cell1=list1.head, *curr_cell2=list2.head; 
    ListNode *cell_to_add;

    makeEmptyList (&merge_res); 
    while (curr_cell1 && curr_cell2) 
    {
        if (*(curr_cell1->dataPtr)>*(curr_cell2->dataPtr))
        {
            insertDataToEndList(&merge_res, *(curr_cell1->dataPtr));
            curr_cell1=curr_cell1->next;
        }
        else
        {
            insertDataToEndList(&merge_res, *(curr_cell2->dataPtr));
            curr_cell2=curr_cell1->next;
        }
    }
    while (curr_cell1)
    {
        insertDataToEndList(&merge_res, *(curr_cell1->dataPtr));
        curr_cell1=curr_cell1->next;
    }
    while (curr_cell2)
    {
        insertDataToEndList(&merge_res, *(curr_cell2->dataPtr));
        curr_cell2=curr_cell2->next;
    }
    return merge_res;
}

void printList (List *list){
    ListNode *curr_cell=list->head;

    while (curr_cell)
    {
        printf("%d, ", *(curr_cell->dataPtr));
        curr_cell=curr_cell->next;
    }
}
void freeList (List *list){
    while (list->head)
        deleteFromBeginnigOfList(list);
}
void deleteFromBeginnigOfList (List *list){
    ListNode *cell_to_delete=list->head;
    list->head=list->head->next;
    if (list->head==NULL)
        list->tail=NULL;
    deallocateListCell (cell_to_delete);
}
void deallocateListCell (ListNode *cell){
    free(cell->dataPtr);
    free (cell);
}

2 个答案:

答案 0 :(得分:1)

在此功能中,您可以访问list-&gt; head-&gt; next,但在第一个 insertDataToEndList,list-&gt; head == NULL,因为你使用了makeEmptyList 结果将是一个分段错误。此外,你想检查是否 list是空的,所以请列出 - > head == NULL。

void insertDataToEndList(List *list, int num)
{    
    ListNode *cell_to_add= createCell (num);
    if (list->head->next==NULL)
        addToEmtyList(list, cell_to_add);
    else
        addToEndList(list, cell_to_add);
}

在此方法中,您必须设置列表的第一个和最后一个节点, 不是下一个所以替换为list-&gt; head和list-&gt; tail而不是lis-&gt; head-&gt; nest。 和list-&gt; tail-&gt; next。

void addToEmtyList(List *list, ListNode *cell)
{
    list->head->next=list->tail->next=cell;

}

你可以这样做:

ListNode *createCell (int num)
{
    ListNode *cell=(ListNode*)malloc(sizeof(ListNode));
    if (!cell)
    {
        printf("memory allocation failed\n");
        exit(1);
    }
    int *temp = (int*)malloc(sizeof(int));
    *temp = num;
    cell->dataPtr=temp;
    cell->next=NULL;

    return cell;
}

否则,我建议你按行进行一次分配,以便更加隐蔽。

答案 1 :(得分:1)

这里有一些错误。大多数都是相对简单的指针错误:

在一个地方你有

curr_cell2=curr_cell1->next;

应该在哪里

curr_cell2 = curr_cell2->next;

addToEmtyList中,您有

list->head->next=list->tail->next=cell

但如果列表为空,则headtail都为空。类似地,insertDataToEndList中的条件应该检查​​list->head而不是list->head->next

更加严重的错误是您正在获取本地变量(num)的地址并将其保存在每个单元格中。保存局部变量的地址是你几乎从不做的事情,因为一旦离开其范围(在这种情况下,当你离开createCell时)指针将变为无效。

如果你真的想拥有一个指向数据的指针,你应该做的是为它分别分配内存。即:

ListNode *createCell (int num){
    ListNode *cell=(ListNode*)malloc(sizeof(ListNode));
    int *data = malloc(sizeof(*data));

    if (!cell || !data)
    {
        printf("memory allocation failed\n");
        exit(1);
    }

    *data = num;
    cell->dataPtr=data;
    cell->next=NULL;

    return cell;
}

另一种选择是将listNode更改为包含int而不是int*。那你就

typedef struct listNode{
    int data;
    struct listNode* next;
}ListNode;

并在createCell

cell->data = num;