delete node(s) in a singly linked list in c
deleteNode()
will remove at most the head or the first non-head node with a matching value. Note, that in the first case you need to update *head
to the previous node. You should also handle head
being NULL
.
Here is an implementation of deleteNodes()
that removes all matching nodes. To avoid the special case of the head node being removed, introduce a tmp
node so we only have to deal with the non-head case:
void deleteNodes(struct NODE **n, int v) {
if(!n) return;
struct NODE tmp = {.prev = *n};
for(struct NODE *p = &tmp; p->prev; ) {
if(p->prev->value == v) {
struct NODE *match = p->prev;
p->prev = p->prev->prev;
free(match);
} else {
p = p->prev;
}
}
*n = tmp.prev;
}
How to correctly delete nodes in singly-linked-list c++
Too much code, this works
void delete_list()
{
size = 0;
while (first != nullptr)
{
Element<N>* next = first->next;
delete first;
first = next;
}
}
Your version was OK for the first loop, but then for some reason you decided you had to delete iter
even though it is only a working variable, not part of the list, and then you decided to delete first
again. I don't know why you felt the need to do that.
Incidentally this is a serious bug
List(const List<N>& other): first(other.first), size(other.size) {}
When you copy a list you need to allocate a new set of nodes, otherwise you end up with two lists sharing the same set of nodes and no way of telling when a node is safe to delete. You probably need to read up on the rule of three.
How do I properly delete nodes of linked list in C++
Node *current = new Node;
Node *previous = new Node;
This code causes memory leaks - you are never deleting this memory. You can declare pointers without memory allocation:
Node *current = nullptr;
Node *previous = nullptr;
delete
will delete the memory of the pointer so you will actually delete Nodes.
But using delete[] for the Node*
is incorrect, it should be used only for arrays - the memory allocated with new[]
. Improper use leads to undefined behaviour.
So, to properly delete nodes delete them with operator delete.
Use memory leaks detection tools to know are there memory leaks in you program.
The code to delete a list element: say, we have pHead which points to the head of the list
(but it would give you much more if you write such things yourself):
Node* pCur = pHead;
Node* pPrev = pCur;
while (pCur && pCur->data != target) {
pPrev = pCur;
pCur = pCur->next;
}
if (pCur==nullptr) // not found
return NOT_FOUND;
if (pCur == pHead) { // first element matches
pHead = pCur->next;
} else {
pPrev->next = pCur->next;
}
// pCur now is excluded from the list
delete pCur; // deallocate its memory
Alternative Using Pointer To Pointer (Community Addition)
The above can take on new light when you use the actual pointers in the list to perform the enumeration. The following starts with pp
being assigned the address of the head pointer (not the node it points to; the actual pointer itself). We walk the list until pp
hold the address of a pointer that is pointing to a node with the target to delete (could be the head pointer, could be a next
pointer in some node, makes no difference). The pointer being addressed is set to its own node's next
value, then the target node is removed.
This really should be watched in a debugger to see how it works, but the algorithm is remarkably simple given what is really going on:
Node **pp = &pHead;
while (*pp && (*pp)->data != target)
pp = &(*pp)->next;
if (*pp)
{
Node *victim = *pp;
*pp = victim->next;
delete victim;
}
Thats all of it. And you get head-node removal without having to special case it for free. Hope this helps as well.
How to delete nodes of a linked list between two indices?
It's all good to use just one struct
, a node for your purpose.
struct node {
char *string;
struct node *next;
};
Then your loop for removing elements between two indices will not delete the right elements if you don't adjust the index according to the changing length of the list. And you must also return the new head of the list.
struct node *deleteList(struct node *head, unsigned from, unsigned to) {
unsigned i;
unsigned count = 0;
for (i = from; i <= to; i++) {
head = delete_at_index(head, i - count);
count++;
}
return head;
}
The help function delete_at_index
looks as follows.
struct node *delete_at_index(struct node *head, unsigned i) {
struct node *next;
if (head == NULL)
return head;
next = head->next;
return i == 0
? (free(head), next) /* If i == 0, the first element needs to die. Do it. */
: (head->next = delete_at_index(next, i -
1), head); /* If it isn't the first element, we recursively check the rest. */
}
Complete program below.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char *string;
struct node *next;
};
void freeList(struct node *head) {
struct node *tmp;
while (head != NULL) {
tmp = head;
head = head->next;
free(tmp->string);
free(tmp);
}
}
struct node *delete_at_index(struct node *head, unsigned i) {
struct node *next;
if (head == NULL)
return head;
next = head->next;
return i == 0
? (free(head), next) /* If i == 0, the first element needs to die. Do it. */
: (head->next = delete_at_index(next, i -
1), head); /* If it isn't the first element, we recursively check the rest. */
}
struct node *deleteList(struct node *head, unsigned from, unsigned to) {
unsigned i;
unsigned count = 0;
for (i = from; i <= to; i++) {
head = delete_at_index(head, i - count);
count++;
}
return head;
}
void pushvar1(struct node **head_ref, char *new_data) {
struct node *new_node = malloc(sizeof(struct node));
new_node->string = strdup(new_data);
new_node->next = (*head_ref);
(*head_ref) = new_node;
}
void printListvar1(struct node *node) {
while (node != NULL) {
printf(" %s ", node->string);
node = node->next;
}
printf("\n");
}
int main(int argc, char **argv) {
struct node *head = NULL;
for (int i = 0; i < 5; i++) {
char str[2];
sprintf(str, "node%d", i);
pushvar1(&head, str);
}
puts("Created Linked List: ");
printListvar1(head);
head = deleteList(head, 0, 2);
puts("Linked list after deleted nodes from index 0 to index 2: ");
printListvar1(head);
freeList(head);
return 0;
}
Test
Created Linked List:
node4 node3 node2 node1 node0
Linked list after deleted nodes from index 0 to index 2:
node1 node0
Delete Node - Linked List - C
The code is removing the wrong item from the linked list:
See:
if ( ( last->x ) == key )
{
printf( "value to be deleted is found" );
node *temp = last->next; // last->next? No, just last.
last->next = last->next->next;
free( temp );
length--;
}
last
is pointing at the element to be removed. But then the code assigns temp
to point at last->next
(NOT last
), and then cuts that from the list.
So by looking at node->next
rather than the current node, it's possible to trim it out since you're starting from the pointer before the one to remove. Basically your code was almost there already.
void deletenode( u8 key )
{
node *ptr = head;
if ( ( ptr->x == key ) )
{
// Delete the first/head element
node *temp = ptr;
head = head->next;
free( temp );
length--;
}
else
{
while ( ptr->next != NULL )
{
if ( ( ptr->next->x ) == key )
{
printf( "value to be deleted is found" );
node *temp = ptr->next;
ptr->next = ptr->next->next;
free( temp );
length--;
}
ptr = ptr->next;
}
}
}
Also I took the liberty of renaming last
to ptr
because it was confusing me.
EDIT: Updated to remove the head cleanly too.
Related Topics
C++0X Has No Semaphores? How to Synchronize Threads
Why Is There No Call to the Constructor
C++ Templates That Accept Only Certain Types
Difference Between Files Written in Binary and Text Mode
How to Handle Wrong Data Type Input
Two Phase Lookup - Explanation Needed
When Does a Constexpr Function Get Evaluated At Compile Time
When Do I Use a Dot, Arrow, or Double Colon to Refer to Members of a Class in C++
What Is Meant With "Const" At End of Function Declaration
Position of Least Significant Bit That Is Set
How to Use Boost in Visual Studio 2010
A Confusing Detail About the Most Vexing Parse
Which, If Any, C++ Compilers Do Tail-Recursion Optimization
Sfinae Working in Return Type But Not as Template Parameter