Bootstrap

删除单向链表中的一个节点

删除单向链表中的一个节点:

法1:

void remove_if(node**head,remove_fn rm){
    for(node**curr=head;*curr;){
        node*entry=*curr;
        if(rm(entry)){
            *curr=entry->next;
            free(entry);
        }
        else curr=&entry->next;
    } 
}

通过使用二级指针,使头节点和其他节点同等,不需要返回值

node**head可以直接修改链表头**head

 

 

 

 

 

详细版:

  1. 函数参数

    • node** head:这是一个二级指针,用于传递链表的头指针。使用二级指针的原因是在函数内部可能需要修改头指针(例如删除头节点时),这样可以保证对链表头指针的修改能够反映到函数外部。
    • remove_fn rm:这是一个函数指针,指向一个用于判断节点是否应被删除的函数。该函数接受一个 node* 类型的参数(表示链表中的一个节点),并返回一个布尔值(通常 0 表示不删除,非 0 表示删除)。
  2. 循环遍历链表

    • for (node** curr = head; *curr; ):这是一个 for 循环,初始化时 curr 指向链表的头指针 head。循环条件 *curr 表示只要当前节点不为空(即 *curr 指向的节点存在),就继续循环。
  3. 判断并删除节点

    • node* entry = *curr;:将当前 curr 所指向的节点(即链表中的当前节点)赋值给 entry
    • if (rm(entry)):调用 rm 函数,传入 entry 作为参数。如果 rm 函数返回值为真(非 0),则执行删除操作。
    • *curr = entry->next;:将 curr 所指向的指针(即当前节点的前一个节点的 next 指针)指向当前节点的下一个节点,从而将当前节点从链表中移除。
    • free(entry);:释放被删除节点的内存,避免内存泄漏。
    • else curr = &entry->next;:如果当前节点不满足删除条件,则将 curr 指向下一个节点的指针,以便在下一次循环中处理下一个节点。
// 假设 remove_fn 是一个函数指针类型,
//它接受一个 node* 类型的参数并返回一个布尔值(通常是 0 或非 0)

// 函数 remove_if 用于从链表中删除满足特定条件的节点
// head 是一个指向 node 类型指针的指针,用于表示链表的头指针(二级指针)
// rm 是一个函数指针,指向一个用于判断节点是否应被删除的函数
void remove_if(node** head, remove_fn rm) {
    // curr 是一个指向 node 类型指针的指针,用于遍历链表,初始指向链表头指针 head
    for (node** curr = head; *curr; ) {
        // entry 指向当前遍历到的节点,即 *curr 所指向的节点
        node* entry = *curr;
        // 调用函数指针 rm 指向的函数,传入当前节点 entry 作为参数
        // 如果该函数返回值为真(非 0),表示当前节点 entry 满足删除条件
        if (rm(entry)) {
            // 将当前指针 curr 所指向的指针(即当前节点的前一个节点的 next 指针)
            // 指向当前节点的下一个节点,实现跳过当前节点的效果
            *curr = entry->next;
            // 释放当前节点的内存,防止内存泄漏
            free(entry);
        }
        // 如果当前节点不满足删除条件
        else {
            // 将 curr 指向下一个节点的指针,即 entry->next 的地址
            // 以便在下一次循环中处理下一个节点
            curr = &entry->next;
        }
    }
}

Linus Torvalds Answers Your Questions - Slashdot