从双向链接列表中正确删除节点

时间:2019-09-11 03:12:19

标签: c

在尝试删除节点时,我可以释放分配的内存,但是无法将其分配为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;
}

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

1 个答案:

答案 0 :(得分:1)

删除节点it时,既需要用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;
}