【问题标题】:Removing nodes from a Doubly linked list correctly正确从双向链表中删除节点
【发布时间】:2019-09-11 03:12:19
【问题描述】:

在尝试删除节点时,我能够释放分配的内存,但无法将其分配给 NULL,因此我的程序停止打印这些地址。我被引导相信我必须使用双指针来做到这一点。

我尝试在释放后等于 NULL,但这会使程序崩溃。

typedef struct Linked_List_type
{
    struct Node_type *first;
    struct Node_type *last;
} LinkedList;
typedef struct Node_type
{
    int data;
    char name[15];
    char phone[15];
    struct Node_type *next;
    struct Node_type *prev;
} Node;
//This is how I insert
void LinkedList_insert (LinkedList * this, int val, char * name, char * phone)
{
//creo un nodo para insertar
    Node *it = this->first;
    Node *newNode = new_Node (val, name, phone);
    if (!this)
    {
        printf ("Lista no creada\n");
    }
    for (it = this->first; it != NULL; it = it->next)
    {
        if (strcmp(it->name, name)==0) //Evitar repeticiC3n
        {
            printf ("Valor repetido\n");
            return;
        }
    }
    if (!this->first)
    {
        newNode->next = NULL;
        this->last = newNode;
        this->first = newNode;
//first y last ocupan el mismo valor, siguiente apunta a nulo
//solo si la lista estC! vacC-a
    }
    else
    {
        newNode->prev = this->last;
        this->last->next = newNode;
        this->last = this->last->next;
    }
}
//This is how I remove 
Bool LinkedList_removestr(LinkedList * this, char * str)
{
    Node * tmp = NULL;
    Node * it = this->first;
    Bool Bandera = FALSE;
    while(it!=NULL)
    {
        if(it->next!=NULL && strcmp(it->name,str)==0)
        {
            tmp=it;
            it=it->next;
            free(tmp);
            Bandera=TRUE;
        }
        if(it->next==NULL && strcmp(it->name,str)==0)//si first es igual al que quiero remover
        {
            tmp=it;
            free(tmp);//no apunto a next porque no hay
            Bandera=TRUE;
        }
        it=it->next;
    }
    return Bandera;
}

删除后,打印列表时,我希望列表跳过被删除的节点地址,或者不显示,但是使用我的删除功能后,打印列表时,节点打印地址,我相信。

【问题讨论】:

    标签: c


    【解决方案1】:

    删除节点it时,需要将前一个节点的next指针替换为it->next,并将下一个节点的前一个指针替换为it->prev

    但是,在执行此操作时,您还必须考虑列表开头和结尾的特殊情况:

    if (it->prev != NULL)
        it->prev->next = it->next;
    else
        this->first = it->next;
    
    if (it->next != NULL)
        it->next->prev = it->prev;
    else
        this->last = it->prev;
    

    您的tmp 变量应该仅用于保存指向要检查的下一个节点的指针,以防it 被释放。将其全部放入您的循环中:

    Bool LinkedList_removestr(LinkedList * this, char * str)
    {
        Node * tmp = NULL;
        Node * it = this->first;
        Bool Bandera = FALSE;
    
        while (it != NULL)
        {
            /* Save it->next, because 'it' may be freed */
            tmp = it->next;
    
            if (strcmp(it->name, str) == 0)
            {
                Bandera = TRUE;
    
                /* Adjust next pointer of previous node */
                if (it->prev != NULL)
                    it->prev->next = it->next;
                else
                    this->first = it->next;
    
                /* Adjust previous pointer of next node */
                if (it->next != NULL)
                    it->next->prev = it->prev;
                else
                    this->last = it->prev;
    
                free(it);
            }
    
            it = tmp;
        }
    
        return Bandera;
    }
    

    【讨论】:

    • 太棒了!你是对的。但是,如果我要删除第一个/最后一个(唯一)节点怎么办? tmp=it->next 会导致崩溃吗?因为 it->next 将是 NULL,即使最后你放 it = tmp 我相信这会阻止程序进入无限循环,它仍然会使我的程序崩溃,或者这会是其他地方的错误吗?先感谢您!很好的解释。
    • tmp = it->next; 如果it->next == NULL 很好 - 它相当于只是tmp = NULL;。只有it == NULL 才会有问题,但我们知道不是,因为如果itNULL,循环就会退出。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-14
    • 2013-09-01
    相关资源
    最近更新 更多