删除单链表中的节点

最近看到Linus在采访中提到一种删除单链表中节点的方法,并说不懂这种方法的人都不理解指针,原话如下:

At the opposite end of the spectrum, I actually wish more people understood the really core low-level kind of coding. Not big, complex stuff like the lockless name lookup, but simply good use of pointers-to-pointers etc. For example, I’ve seen too many people who delete a singly-linked list entry by keeping track of the “prev” entry, and then to delete the entry, doing something like

if (prev)
prev->next = entry->next;
else
list_head = entry->next;

and whenever I see code like that, I just go “This person doesn’t understand pointers”. And it’s sadly quite common.

People who understand pointers just use a “pointer to the entry pointer”, and initialize that with the address of the list_head. And then as they traverse the list, they can remove the entry without using any conditionals, by just doing a “*pp = entry->next”.

So there’s lots of pride in doing the small details right. It may not be big and important code, but I do like seeing code where people really thought about the details, and clearly also were thinking about the compiler being able to generate efficient code (rather than hoping that the compiler is so smart that it can make efficient code *despite* the state of the original source code).

其实大神说的这种方法的好处就是: 在删除节点时,不用区别该节点是否是链表的第一个节点,具体实现代码如下:

 1 //定义最简单的链表结构
 2 typedef struct node
 3 {
 4     int value;
 5     struct node* next;
 6 }Node;
 7
 8 Node** pp = &list_head;
 9 Node* entry = list_head;
10
11 //假设要删除的节点值是9
12 while(entry->value != 9)
13 {
14     //每次迭代都将next变量的地址保存到pp中
15     //next是指针变量,故它的地址就是地址的地址了,即Node**
16     pp = &entry->next;
17     entry = entry->next;
18 }
19
20 //将前置节点的next值指向下一个节点
21 *pp = entry->next;

各变量内容的变化如下:

内存地址:0x1               0x2                       0x4              0x8
        list_head=0x2     node1(value:10,           node2(value:9,   node3(value:8)
                                next变量的内存地址:
                                0x3                       0x5              0x9
                                next:0x4)                 next:0x8         next:NULL
 
迭代过程:
pp=0x1
entry=0x2
 
pp=0x3
entry=0x4
 
查找到要删除的节点:
*pp=0x8 => 0x2
           node1(value:10,
                 0x3
                 next:0x4 => 0x8)

这样,无论需要删除的是node1(头节点)还是普通节点,都不需要判断前置节点是否为头节点的指针。
时间: 2024-10-24 13:08:58

删除单链表中的节点的相关文章

删除单链表中第i个节点

单链表的删除操作是将单链表的第i个节点删去.具体步骤如下: (1)找到节点ai-1的存储位置p,因为在单链表中节点ai的存储地址是在其直接前趋节点ai-1的指针域next中: (2)令p->next指向ai的直接后继节点ai+1: (3)释放节点ai的空间: #include <stdio.h> #include <stdlib.h> typedef struct node { int data; struct node *next; } NODE; // 尾插法创建单链表(

13.删除单链表中重复的元素

13.删除单链表中重复的元素 思路: 用Hashtable辅助,遍历一遍单链表就能搞定.同高级函数9的原因,我不太会使用C++STL中的hash.而如果使用set集合来存储链表中的所有的值,实际上效率和每次重新遍历单链表是一样的.“用了c++标准库中的set来保存访问过的元素,所以很方便的就可以判断当前节点是否在set集合中,直接使用set提供的find函数就可以了.而且使用set的查找在时间复杂度上比较低.”我不太清楚STL中set集合的实现方式,如果是基于类似hash结构的话,那自然效率O(

【LeetCode-面试算法经典-Java实现】【203-Remove Linked List Elements(删除单链表中的元素)】

[203-Remove Linked List Elements(删除单链表中的元素)] [LeetCode-面试算法经典-Java实现][所有题目目录索引] 代码下载[https://github.com/Wang-Jun-Chao] 原题 Remove all elements from a linked list of integers that have value val. Example Given: 1 --> 2 --> 6 --> 3 --> 4 --> 5

009实现一个算法来删除单链表中的一个结点,只给出指向那个结点的指针(keep it up)

呵呵,这个题不能直接删除已知的结点,因为是单链表,不知道前驱,只知道 后继结点,直接删除会使链表断开.不过我们可以删除已知结点的后继结点, 把后继结点的值赋值给已知结点. #include <iostream> struct Node { int data; Node* next; }; bool removeNode(Node* vNode) { if (vNode == NULL || vNode->next == NULL) return false; Node* pNext =

链表:在不给出整个链表头结点的情况下,删除单链表中的某个节点

问题描述: 有一个包含int型节点值的单链表,给定一个链表中的节点node,但不给定整个链表的头结点,删除链表中的某个结点. 算法实现: class Node { public int value; public Node next; public Node(int value) { this.value = value; } } public void removeWiredNode(Node node) { if(node == null) { return; } Node next = n

删除单链表中重复的值(Java版)

题目:删除带头结点的单链表中重复值的元素(即让每种值的元素只有一个) 解题思路: 用一个动态辅助存储数组,每次要向辅助数组中放入元素时,让辅助数组的长度加1,最长时与单链表一样长,设一个指针p,让它指向头结点,从单链表中第一个元素开始,将它的值放入辅助数组中,然后依次访问单链表后面的元素,用该元素的值与数组中所有已经被赋值的元素的值进行比较,如果不等于数组中任何元素的值,那么让p的next指向该结点的next指针,删除该结点元素,否则令p指向p的next指针,并将当前访问的节点元素的值依次放入辅

删除单链表中重复的值

题目:删除带头结点的单链表中重复值的元素(即让每种值的元素只有一个) 解题思路: 用一个动态辅助存储数组,每次要向辅助数组中放入元素时,让辅助数组的长度加1,最长时与单链表一样长,设一个指针p,让它指向头结点,从单链表中第一个元素开始,将它的值放入辅助数组中,然后依次访问单链表后面的元素,用该元素的值与数组中所有已经被赋值的元素的值进行比较,如果不等于数组中任何元素的值,那么让p的next指向该结点的next指针,删除该结点元素,否则令p指向p的next指针,并将当前访问的节点元素的值依次放入辅

删除单链表中重复的结点

先批评下<<数据结构实验教程(C语言版) 清华大学出版社 :王国钧主编>>这本书,CTMD,错误真多! *删除单链表重复结点 算法-:第一个跟后面比较,同则删除;第二个...第n个; 采用 *算法二:先排序, 将排好后的相同结点删除*/ void delSameNodeDLink(LinkList h) {//内外循环 LinkList p1, p2, p3; p1 = h; while (p1->next) { p2 = p1->next; //1 p3 = p2-&

[转]用O(1)的时间复杂度删除单链表中的某个节点

给定链表的头指针和一个结点指针,在O(1)时间删除该结点.链表结点的定义如下: struct ListNode {      int        m_nKey;       ListNode*  m_pNext; }; 函数的声明如下: void DeleteNode(ListNode* pListHead, ListNode* pToBeDeleted); 这是一道广为流传的Google面试题,考察我们对链表的操作和时间复杂度的了解,咋一看这道题还想不出什么较好的解法,但人家把题出在这,肯定