1. Delete 4

Code:
```  Head
|
v
+---+    +---+    +---+    +---+    +---+
| 5 |--->| 4 |--->| 3 |--->| 2 |--->| 1 |--->NULL
+---+    +---+    +---+    +---+    +---+```
Step 1, advance current to the correct node.
Code:
```  Head     current
|        |
v        v
+---+    +---+    +---+    +---+    +---+
| 5 |--->| 4 |--->| 3 |--->| 2 |--->| 1 |--->NULL
+---+    +---+    +---+    +---+    +---+```

Step 2, bypass the node to be deleted.
Somehow, you need to make the node containing 5 point to the node containing 3.
Code:
```  Head     current
|        |
v        v
+---+    +---+    +---+    +---+    +---+
| 5 |-+  | 4 | +->| 3 |--->| 2 |--->| 1 |--->NULL
+---+ |  +---+ |  +---+    +---+    +---+
+--------+```
This is normally achieved by having another pointer variable that tracks the previous node.

Code:
```void delete( struct node **head, int value)
{
struct node *prev = NULL;

while (current != NULL)
{

// the current node becomes the previous node
prev = current;
current = current->next;
}
}``` 2. Originally Posted by Salem Delete 4

Code:
```  Head
|
v
+---+    +---+    +---+    +---+    +---+
| 5 |--->| 4 |--->| 3 |--->| 2 |--->| 1 |--->NULL
+---+    +---+    +---+    +---+    +---+```
Step 1, advance current to the correct node.
Code:
```  Head     current
|        |
v        v
+---+    +---+    +---+    +---+    +---+
| 5 |--->| 4 |--->| 3 |--->| 2 |--->| 1 |--->NULL
+---+    +---+    +---+    +---+    +---+```

Step 2, bypass the node to be deleted.
Somehow, you need to make the node containing 5 point to the node containing 3.
Code:
```  Head     current
|        |
v        v
+---+    +---+    +---+    +---+    +---+
| 5 |-+  | 4 | +->| 3 |--->| 2 |--->| 1 |--->NULL
+---+ |  +---+ |  +---+    +---+    +---+
+--------+```
This is normally achieved by having another pointer variable that tracks the previous node.
This is the same process that I have done in a post #26.

Basic process is understandable but very difficult to convert into code 3. Originally Posted by Kittu20 This is the same process that I have done in a post #26.
But not what you are doing in code...

May I suggest there's a better way to implement single linked lists with 2 sentinel nodes?
I believe I already told this... 4. Sedgewick like single linked list:
Code:
```EMPTY LIST

+------+
V      |
+---+       +---+   |
|   |------>|   |---+
+---+       +---+
This structure must obey some ground rules:

1 - Never try to delete head or tail nodes;
2 - Never try to add a node after tail node;
3 - Insert or delete nodes AFTER a specific node.

The node structure is this:
Code:
`struct node { struct node *next; };`
Without any data! Only the link to the next node. The list structure is like this:
Code:
`struct list { struct node head, tail; };`
Yep... head and tail aren't pointers! And we must initialize an object of this structure with this macro:
Code:
```#define INIT_LIST(list__) (struct list){ .head.next = &(list_).tail, \
.tail.next = &(list__).tail }```
Like this:
Code:
`struct list mylist = INIT_LIST(mylist);`
These structures allow polymorphic nodes. All you have to do is to make sure the first member of any node is the next pointer. Like in:
Code:
```struct mynode {
struct node *next;

// ... a bunch of my node objects here
};```
Here's the insert after node function:
Code:
```void slist_insertAfter( struct node *node, struct node *new )
{
new->next = node->next;
node->next = new;
}```
And the delete after:
Code:
```// return NULL if next node is tail.
struct node *slist_deleteAfter( struct node *node )
{
struct node *next;

next = node->next;
if ( next == next->next )
return NULL;

node->next = next->next;

return next;
}```
In this particular example I choose to return NULL if the next node is tail.
To test if a list is empty is very simple:
Code:
```_Bool slist_empty( struct list *list )
{ return list->head.next == &list->tail; }```
Another useful routine could be:
Code:
```_Bool slist_istail( struct node *node )
{ return node == node->next; }```
To empty the entire list is simple:
Code:
```void slist_clear( struct list *list, void (*dtor)( void * ) )
{
while ( 1 )
{
struct node *node;

if ( ! node )
break;

if ( dtor )
dtor( node );
}
}```
Where's the nodes allocations? You may ask. They are NOT part of the list manipulation (and never should be). Here's an example of usage:
Code:
```// macro for list iteration.
#define for_each(iter__,list__) \
for ( (iter__) = (list__)->head.next; \
(iter__) != (iter__)->next; \
(iter__) = (iter__)->next )

int main( void )
{
struct list list = LIST_INIT(list);
struct node *i; // list iterator.

struct mynode {
struct node *next;

int value;
};

struct mynode *p;

// As an example I did not test the success or failure of malloc here!
// you should do it... Notice the allocation is NOT part of the
// list manipulation routines.

p = malloc( sizeof *p ); p->value = 1;
slist_insertAfter( &list.head, (struct node *)p ); i = (struct node *)p;

p = malloc( sizeof *p ); p->value = 2;
slist_insertAfter( i, (struct node *)p ); i = (struct node *)p;

p = malloc( sizeof *p ); p->value = 3;
slist_insertAfter( i, (struct node *)p );

for_each( i, &list )
{
p = (struct mynode *)i;

printf( "%d ", p->value );
}

putchar( '\n' );

slist_clear( &list, free );   // using free() as destructor.
}``` 5. Here's how simple the slist_empty, slist_insertAfter and slist_deleteAfter is compiled to assembly for x86-64:
Code:
```slist_empty:
lea      rax, [rdi+8]
cmp      rax, [rdi]
sete     al
ret

slist_insertAfter:
mov      rax, [rdi]
mov      [rsi], rax
mov      [rdi], rsi
ret

slist_deleteAfter:
mov      rax, [rdi]
mov      rdx, [rax]
cmp      rdx, rax
je       .is_tail
mov      [rdi], rdx
ret

align 4
.is_tail:
xor      eax, eax
ret```
Just make them static inline and they will be extremely fast.

Compare this to the usual last node points to NULL approach and you'll see we have much less "special cases". 6. Another thing: If you plan to unlink the next node based on some criteria, the for_each macro is no good. We must keep track of the next node, after it. So, this other macro is safer, in that cases:
Code:
```#define for_each_safe(iter__,tmp__,list__) \
for ( (iter__) = (list__)->head.next, (tmp__) = (iter__)->next; \
(iter__) != (iter__)->next; \
(iter__) = (tmp__) )```
The usage:
Code:
```struct node *i; // iterator
struct node *tmp; // temporary (used only inside for_each_safe)

for_each_safe( i, tmp, &list )
{
struct mynode *p = (struct mynode *)i;

// some criteria...
if ( p->value == 2 ) slist_deleteAfter( i, free );
}``` 7. @flp1969 The assembler isn't helpful at all.

> This is the same process that I have done in a post #26.
You've only drawn the end result.
You need to draw all the steps taken if you hope to understand what the code needs to do.

Deleting node 2
Code:
```p = NULL

c
+---+    +---+    +---+    +---+    +---+
| 5 |--->| 4 |--->| 3 |--->| 2 |--->| 1 |--->NULL
+---+    +---+    +---+    +---+    +---+
Is c pointing at 2? No - advance
p = c ; c = c->next;

p        c
+---+    +---+    +---+    +---+    +---+
| 5 |--->| 4 |--->| 3 |--->| 2 |--->| 1 |--->NULL
+---+    +---+    +---+    +---+    +---+
Is c pointing at 2? No - advance
p = c ; c = c->next;

p        c
+---+    +---+    +---+    +---+    +---+
| 5 |--->| 4 |--->| 3 |--->| 2 |--->| 1 |--->NULL
+---+    +---+    +---+    +---+    +---+
Is c pointing at 2? No - advance
p = c ; c = c->next;

p        c
+---+    +---+    +---+    +---+    +---+
| 5 |--->| 4 |--->| 3 |--->| 2 |--->| 1 |--->NULL
+---+    +---+    +---+    +---+    +---+
Is c pointing at 2? Yes!```
So now you're in the situation where the current pointer is pointing to the node to delete, and the previous pointer is pointing to its predecessor.

Cartoon Guide to Data Structures — Singly Linked Lists | by Rajesh Pillai | Full Stack Engineering | Medium

> Basic process is understandable but very difficult to convert into code
Then you haven't understood it. 8. Originally Posted by Salem @flp1969 The assembler isn't helpful at all.
It is there just to show what the C compiler creates and to show the three routines are compiled to a very simple form.
Ignore it if you don't like.

It's not 'helpful'... it is 'informative'. 9. Originally Posted by flp1969 It is there just to show what the C compiler creates and to show the three routines are compiled to a very simple form.
Ignore it if you don't like.

It's not 'helpful'... it is 'informative'.
Not for beginner programmers that make up the majority of posters here that are learning C, and have had no exposure to Assembler code. It might as well be a foreign spoken language they can't speak or read.

Stick to giving answers and sample code in C, in this, the C forum. 10. Originally Posted by rstanley Not for beginner programmers that make up the majority of posters here that are learning C, and have had no exposure to Assembler code. It might as well be a foreign spoken language they can't speak or read.

Stick to giving answers and sample code in C, in this, the C forum.
I don't care about "the majority" and won't restrict my answers, posts or opinions...
Unless is writen, somewhere, that this forum is ONLY for beginners. If it is the case I'll ask to DELETE my account AND my posts. 11. It's not "helpful" because it's about as useful as dumping calculus on someone who's barely got to grips with addition and subtraction.

It's not "helpful" to dump a complete re-design of a linked list on the OP because you believe it's "better". You've no idea what the terms of reference are for the OP, so it's no good them copy/pasting something way outside their experience.

> I don't care about "the majority" and won't restrict my answers, posts or opinions...
Sure, just don't expect people to keep quiet about it either. 12. don't know what to do after this

Code:
``` #include<stdio.h>#include<stdlib.h>

struct node
{
int data;
struct node *next;
};

void delete( struct node **head, int value)
{
struct node *prev = NULL;

while (current != NULL)
{
if ( current-> data == 2)
{
printf("found = %d \n", value);
}

prev = current;
current = current -> next;

}
}

void instert( struct node **current, int value)
{
struct node *new = malloc(sizeof(struct node));

if ( new != NULL)
{
new-> data = value;
new -> next = *current;
*current = new;
}
}

void List(struct node *current)
{
while (current !=NULL)
{
printf("%d -> ", current -> data);
current = current -> next;
}
printf("NULL\n");
}

int main ()
{

printf("\n");
return 0;
}``` 13. > if ( current-> data == 2)
Try comparing with the value parameter.

Well you look at your diagrams, and that you have two pointers called prev and current.

Then you stare at this diagram.
Code:
```prev     current
|        |
v        v
+---+    +---+    +---+    +---+    +---+
| 5 |-+  | 4 | +->| 3 |--->| 2 |--->| 1 |--->NULL
+---+ |  +---+ |  +---+    +---+    +---+
+--------+```
Then you consider the possibility of what
prev->next = current->next;
might do. Popular pages Recent additions current, delete, instert&head, node, struct 