木木mumuqy 2024-05-07 10:52 采纳率: 0%
浏览 5

C语言数据结构删除元素的BUG,一度以为见鬼了

下边这段代码删除操作,我知道我写的有问题,但是神奇的是结果却是正确的,能正常运行,但是我取调试的时候就线出现delete中陷入死循环永远执行不完,我都特喵以为我见鬼了,这是什么鬼


#include <stdio.h>
#include <stdlib.h>
/*
单链表的操作
*/
typedef struct Node
{
    int data;
    struct Node *next;
} Node;
//列表初始化
Node *initList()
{
    Node *list = (Node *)malloc(sizeof(Node));
    list->data = 0;
    list->next = NULL;
    return list;
}
//头插法
void headInsert(Node *list, int data)
{
    Node *node = (Node *)malloc(sizeof(Node));
    node->data = data;
    node->next = list->next;
    list->next = node;
    list->data++;

}
//尾插法
void tailTnsert(Node *list, int data){
    Node *head = list;
    Node *node = (Node *)malloc(sizeof(Node));
    node->data = data;
    node->next = NULL;
    head = head->next;
    while(head->next){
        head = head->next;
    }
    head->next = node;
    list->data++;
}
//单链表的插入,在链表的第i个位置插入x的元素
void LinkedListInsert(Node *list,int i,int data) {
    Node *pre;                      //pre为前驱结点
    pre = list;
    int tempi = 0;
    for (tempi = 1; tempi < i; tempi++) {
        pre = pre->next;                 //查找第i个位置的前驱结点
    }
    Node *node = (Node *)malloc(sizeof(Node));;                                //插入的结点为p
    node->data = data;
    node->next = pre->next;
    pre->next = node;
    list->data++;
}

//删除 单个 
// void delete(Node *list, int data){
//     Node *pre = list;
//     Node *current = list->next;
//     while (current)
//     {
//         if (current->data == data)
//         {
//             pre->next = current->next;
//             free(current);
//             break;
//         }
//         pre = current;
//         current = current->next;
//     }
//     list->data--;
// }
//这里如果删除所有的怎么弄;删除所有
void delete(Node *list, int data){
    Node *pre = list;
    Node *current = list->next;
    while (current)
    {
//        printf("%d :", current->data);
        if (current->data == data)
        {
            pre->next = current->next;
            current = current->next;
            free(current);

            list->data--;//我写的这段可能存在内存的问题,因为我释放掉了但是current还能用,释放掉的还是之前的
            // pre->next = current->next;
            // Node *temp = current->next; // 保存下一个节点的指针
            // free(current);
            // current = temp;
        }
        else{
            pre = current;
            current = current->next;
        }
        
    }
    
}
// void delete(Node *list, int data){
//     Node *pre = list;
//     // Node *current = list->next;
//     while (pre->next)
//     {
//         Node *p = pre->next;//暂存当前指针要释放的节点,用于释放该节点,此外用于不需要释放的时候指针向后移动
//         // printf("%d  :", p->data);
//         if (p->data == data)//这里要注意p->data解引用,所以p不能为空
//         {
//             pre->next = p->next;//前结点指向要释放的结点的下一结点
//             free(p);
//             list->data--;
//         }
//         else{
//             pre = pre->next;//移动前驱指针
//         }
        
//     }
    
// }



// //单链表的删除,在链表中删除值为x的元素
 
// LinkedList LinkedListDelete(LinkedList L,int x) {
//     Node *p,*pre;                   //pre为前驱结点,p为查找的结点。
//     p = L->next;
     
//     while(p->data != x) {              //查找值为x的元素
//         pre = p;
//         p = p->next;
//     }
//     pre->next = p->next;          //删除操作,将其前驱next指向其后继。
//     free(p);
     
//     return L;
// }
 
//链表内容的修改,再链表中修改值为x的元素变为为k。
void LinkedListReplace(Node* list,int data,int newdata) {
    Node *p=list->next;
    int i=0;
    while(p){
        if(p->data==data){
            p->data=newdata;
        }
        p=p->next;
    }
}

//打印链表
void printList(Node *list){
     list = list->next;

    while (list)
    {
        printf("%d   ", list->data);
        list = list->next;
    }
}



int main(int argc, char const *argv[])
{
    Node *list = initList();
    headInsert(list, 1);
    headInsert(list, 2);
    headInsert(list, 3);
    headInsert(list, 4);
    headInsert(list, 5);
    headInsert(list, 288);
    tailTnsert(list, 6);
    tailTnsert(list, 7);
    tailTnsert(list, 8);
    tailTnsert(list, 9);
    tailTnsert(list, 10);
    tailTnsert(list, 288);
    LinkedListInsert(list, 5, 288);
    LinkedListInsert(list, 5, 288);
    delete(list, 288);
    // LinkedListReplace(list, 288, 10000);
    printList(list);
    return 0;
}

  • 写回答

3条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-05-07 10:52
    关注

    引自免费微信小程序:皆我百晓生

    在您提供的代码中,delete 函数存在一个潜在的无限循环问题。当删除第一个匹配到的数据时,代码中的 free(current); 操作会释放当前节点,然后将 current 指针设置为 current->next。但在接下来的循环中,由于没有更新 pre 的值,导致 pre->next 仍然指向已经释放的内存,这可能会引发未定义行为。

    为了修复这个问题,您应该在释放 current 后,同时更新 pre 的值。以下是修复后的代码:

    void delete(Node *list, int data){
        Node *pre = list;
        Node *current = list->next;
        while (current)
        {
            if (current->data == data)
            {
                pre->next = current->next;
                free(current);
                current = pre->next; // 更新current为新的前一个节点
                list->data--;
            }
            else{
                pre = current;
                current = current->next;
            }
            
        }
    }
    

    通过上述更改,程序在删除节点时不会进入无限循环,并且可以正确地从链表中移除指定的值。现在,您可以重新编译并运行您的程序,它应该按预期工作。

    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 5月7日

悬赏问题

  • ¥15 想用adb命令做一个通话软件,播放录音
  • ¥30 Pytorch深度学习服务器跑不通问题解决?
  • ¥15 部分客户订单定位有误的问题
  • ¥15 如何在maya程序中利用python编写领子和褶裥的模型的方法
  • ¥15 Linux权限管理相关操作(求解答)
  • ¥15 Bug traq 数据包 大概什么价
  • ¥15 在anaconda上pytorch和paddle paddle下载报错
  • ¥25 自动填写QQ腾讯文档收集表
  • ¥15 DbVisualizer Pro 12.0.7 sql commander光标错位 显示位置与实际不符
  • ¥15 android 打包报错