【问题标题】:linked list is not removing/adding first heads链表没有删除/添加第一个头
【发布时间】:2021-02-11 15:16:03
【问题描述】:

我正在创建一个在匹配时添加/删除头部的程序,但是它不起作用。这两个功能有什么问题吗?我有更多的链表代码,但这是我在程序中使用的两个。

它们应该类似于堆栈的推送/弹出功能

linkedList* createLinkedList()
{
    linkedList* list;
    list = malloc(sizeof(linkedList));
    list->size = 0;
    list->head = NULL;
    list->tail = NULL;
    return list;
}
void insertStart(linkedList* list, void* inData)
{
    listNode* node;
    node = (listNode*)malloc(sizeof(listNode));
    node->data = inData;
    list->size++;
    if (list->head == NULL)
    { 
        list->head = node;
        list->tail = node;
        node->next = NULL;
        node->prev = NULL;
    }
    else
    { 
    
        list->head->prev = node;
        node->next = list->head;
        node->prev = NULL;
        list->head = node;
    }
}

void* removeStart(linkedList* list)
{
    listNode* removed = NULL;
   /* void* outData = NULL;*/
 
        removed = list->head;
        list->head = list->head->next;
        list->head->prev = NULL;
        list->size -= 1;
       /* outData = removed->data;
        free(removed);*/
   
    return removed;
}

【问题讨论】:

  • 只是一个旁注,除非您对 size 成员有特殊需要,否则当您向列表添加更多功能时,size 成员可能很难维护 - 并且用处有限。 (除了回答“我有多少节点?”或者如果您限制节点数量)请记住一些事情。

标签: c linked-list stack doubly-linked-list function-definition


【解决方案1】:

虽然insertStart 可以正常工作,但可以大大简化:

void insertStart(linkedList* list, void* inData)
{
    listNode* node = malloc(sizeof *node);
    node->data = inData;
    node->next = list->head;
    node->prev = NULL;
    if (list->head)
        list->head->prev = node;
    else
        list->tail = node;
    list->head = node;
    list->size++;
}

然而,真正的问题是removeStart。它有几个明显的缺陷:

  1. 它不管理 tail 指针。
  2. 它假定列表非空。
  3. 返回的结果不正确。 (你想返回数据成员;而不是节点指针)

前者将彻底破坏需要妥善管理的尾指针的一切;如果一个空列表,第二个将调用 undefined 行为。最后一项只是监督。所有这些都可以在不到 20 行代码中解决:

void* removeStart(linkedList* list)
{
    void *data = NULL;

    if (list->head)
    {
        listNode* removed = list->head;
        list->head = removed->next;
        if (list->head)
            list->head->prev = NULL;
        else
            list->tail = NULL;
        data = removed->data;
        free(removed);
        --list->size;
    }
    return data;
}

【讨论】:

    【解决方案2】:

    函数insertStart 包含重复代码。此外,为了防止未定义的行为,它应该检查是否成功分配了新节点的内存。

    函数可以通过以下方式声明和定义。

    int insertStart(linkedL ist *list, void* inData )
    {
        listNode *node = malloc( sizeof( listNode ) );
        int success = node != NULL;
    
        if ( success )
        {
            node->data = inData;
            node->next = list->head;
            node->prev = NULL;
    
            if ( list->head == NULL )
            {
                list->tail = node;
            }
            else
            {
                list->head->prev = node;
            }
    
            list->head = node;
            ++list->size;
        }
    
        return success;
    }
    

    函数emoveStart 的主要问题是它不检查列表是否为空。此外,当列表包含一个节点时,它不会更新指针tail 指向的节点。

    函数可以通过以下方式定义

    void *  removeStart( linkedList *list )
    {
        void *data = NULL;
    
        if ( list->head != NULL )
        {
            listNode *removed = list->head;
            data = removed->data;
    
            list->head = list->head->next;
    
            if ( list->head == NULL )
            {
                list->tail = NULL;
            }
            else
            {
                list->prev = NULL;
            }
    
            free( removed );
            --list->size;
        }
    
        return data;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-04
      • 1970-01-01
      • 1970-01-01
      • 2021-05-01
      • 2013-10-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多