4

as far as I can see, you can do:

  1. Find the node to remove.
  2. node.previous.next = node.next
  3. node.next.previous = node.previous
  4. node.previous = null
  5. node.next = null
  6. Dispose of node if you're in a non-GC environment

If your list is a double linked.

But how do you do it with a single linked list? I have tried a lot of things, with no avail :( I simply get it to remove a specific index instead or it does nothing at all

14 Answers 14

11

Start at the beginning of the list. Maintain a reference to the current item (currentItem) and the previous item (previousItem). Linearly search for the item that you want to remove always walking with previousItem = currentItem, currentItem = currentItem.Next. If the item that you want to remove is the head of the list, reassign the head of the list to currentItem.Next. Otherwise, set previousItem.Next = currentItem.Next. If necessary (as you say, in a non-GC environment) dispose of currentItem.

Basically you are using previousItem to mimic the behavior of a currentItem.Previous in the case of a doubly-linked list.

Edit: This is a correct implementation of Delete:

public void Delete(int rangeStart, int rangeEnd) {
    Node previousNode = null, currentNode = Head;
    while (currentNode != null) {
        if (currentNode.Data >= rangeStart && currentNode.Data <= rangeEnd) {
            if (previousNode == null) {
                Initial = currentNode.Next;
            }
            else {
                previousNode.Next = currentNode.Next;
            }
        }
        else {
            previousNode = currentNode;
        }
        currentNode = currentNode.Next;
    }
}
Sign up to request clarification or add additional context in comments.

12 Comments

That is clever! I had not thought of mimicing! Although, I does not seem to work, if the item is the very first item in my list?
@CasperT: If the item is the very first in the list you merely reassign the head of the list to currentItem.Next and, if necessary, dispose of currentItem. In this case the previousItem reference is not needed.
I think I am a little off the track. I have updated my question :)
Oh and also if the item is in the end of my list - won't work either :)
@CasperT: What you have provided will not work. Consider 1->2->3->4->5 and calling Delete(1, 2). You will end with the list 2->3->4->5 because the Initial node will not be correctly set. This is because you only modify Initial when previousNode is null. After you've walked over the initial item in the list you will have Initial pointing to the node containing 2, previousNode pointing to the node containing 1 and currentNode pointing to the node containing 2. Thus the next time through the loop previousNode will not be null so Initial will not change. I'll provide a fix.
|
5

You keep track of the last node while you try to find the "current node".

Then you can wire up the previouse.next to current.next and you are done

1 Comment

It doesn't seem to work if the desired item(s) is either in the end or at the start of the list
3

Well, you could just use LinkedList<T> and Remove; but manually:

  • iterate forwards until you find the node you want to remove keeping the previous node available in a variable at each point
  • set prev.next = node.next
  • go home

4 Comments

Should check prev for null!Isnt it?
calling LinkedList<T> "language-agnostic" would be a bit of a stretch ;-)
@HerdplattenToni - check the edit history; it was C# at one point!
@Marc Gravell: I made the edit because his first version of the post seemed to be looking for the idea and not code in a specific language (as indicated by his walkthrough on how to do it for a doubly-linked list). Now that he has added code, I have added the tag back. It does not appear that he is using LinkedList<T> however.
2

The following code uses recursion to keep track of previous node: Source: http://www.cs.bu.edu/teaching/c/linked-list/delete/

nodeT *ListDelete(nodeT *currP, elementT value)
{
  /* See if we are at end of list. */
  if (currP == NULL)
    return NULL;

  /*
   * Check to see if current node is one
   * to be deleted.
   */
  if (currP->element == value) {
    nodeT *tempNextP;

    /* Save the next pointer in the node. */
    tempNextP = currP->next;

    /* Deallocate the node. */
    free(currP);

    /*
     * Return the NEW pointer to where we
     * were called from.  I.e., the pointer
     * the previous call will use to "skip
     * over" the removed node.
     */
    return tempNextP;
  }

  /*
   * Check the rest of the list, fixing the next
   * pointer in case the next node is the one
   * removed.
   */
  currP->next = ListDelete(currP->next, value);


  /*
   * Return the pointer to where we were called
   * from.  Since we did not remove this node it
   * will be the same.
   */
  return currP;
}

Comments

2

You may find the comprehensive implementation of Singly Linked List with all the functions such Add, Remove, InsertAt etc., here. http://tech.bragboy.com/2010/01/linked-lists.html Note: This has a working Java code + Test classes so that you would not miss out on anything that a singly linked list is made of,

Comments

1

This is the primary weakness of the singly-linked list. You'll either need to have a reference to the previous node, or scan through the list from the beginning.

Comments

1

keep remebering the last node you been too.

//PSEUDO CODE

Node prevnode = null;
foreach (node n in nodes)
{
    if (n.name.equals(name))
    {
        if (prevnode != null)
        {
            prevnode.next = n.next;
        }
        remove n;
        break;
    }

    prevnode = n;
}

1 Comment

I am not sure how you could implement a foreach :)
0

Almost ironic you should just ask this. I'm trying to brush up on my singly linked lists too. I just wrote this function in C++ that seems to work:

void pop_back() {
    if(head == NULL) {
        return;
    }

    if(head->next == NULL) {
        delete head;
        head = NULL;
        return;
    }

    Node *iter = head;
    while(iter->next->next != NULL) {
        iter = iter->next;
    }
    delete iter->next;
    iter->next = NULL;
}

For popping the last element, but you can modify it slightly to work in the middle, I'm sure. Idea is pretty much the same in C#.

3 Comments

Hi. I wrote a pop() earlier today. pastebin.com/m7bd8ca12 It seems to work and is much shorter :) it does need a null validate though
Well, that pops the first element. Mine pops the last... not quite as easy.
Oh, okay, I am treating my list as a stack :) I did not notice that
0
struct node_t {
    int data;
    struct node_t *next;
}

void delete_node( struct node_t *random) {
    struct node_t *temp;

    /* Save the ptr to the next node */
    temp = random->next;

    /* Copy stuff from the next node to this node */
    random->data = random->next->data;
    random->next = random->next->next;

    /* Delete the next node */
    free (temp);

    return;
}

This should work on most Operating Systems in my opinion.

Comments

0
    static void Main(string[] args)
    {
        LinkedList<string> ll = new LinkedList<string>();

        ll.AddLast("uno");
        ll.AddLast("dos");
        ll.AddLast("tres");

        ll.Remove(ll.Find("uno")); // Remove

        foreach (string item in sl)
        {
            Console.WriteLine(item);
        }

        Console.ReadKey();
    }

Comments

0

Here is a working solution for deleting a node from LinkedList in C#.

  • First, Looping through nodes till we find the matching node.
  • Second, update Previous Node and Current Node value.
  • If First Node, i.e. previous node is null, point Head to Next Node.

    class LinkedList
    {
        private Node Head { get; set; } = null;
    
        public void Insert(int d)
        {
            Console.WriteLine("Insert : " + d);
            var newNode = new Node() { Data = d, Next = null };
            if (Head == null)
            {
                Head = newNode;
            }
            else
            {
                newNode.Next = Head;
                Head = newNode;
            }
        }
    
        public void Delete(int d)
        {
            Console.WriteLine("Delete : "+d);
            var node = Head;
            Node currNode = Head;
            Node prevNode = null;
            while (node != null)
            {
                currNode = node;
                if (node.Data == d)
                {
                    if(prevNode != null)
                    {
                        prevNode.Next = currNode.Next;
                    }
                    else
                    {
                        Head = Head.Next;
                    }
                    break;
                }
                prevNode = currNode;
                node = node.Next;
            }
        }
    
        public void Print()
        {
            var list = Head;
            Console.Write("Elements: ");
            while (list != null)
            {
                Console.Write(list.Data + " ");
                list = list.Next;
            }
            Console.WriteLine();
        }
    }
    

Comments

0

To Remove a particular Node from a Single LinkedList based on the index value of the List item. Below is the code

 public void DeleteNode(int nodeIndex)
    {
        int indexCounter = 0;
        Node TempNode = StartNode;
        Node PreviousNode = null;
        while (TempNode.AddressHolder != null)
        {
            if (indexCounter == nodeIndex)
            {
                PreviousNode.AddressHolder = TempNode.AddressHolder;
                break;
            }
            indexCounter++;
            PreviousNode = TempNode;
            TempNode = TempNode.AddressHolder;
        }
    }

Complete Code can be found on http://fumycoder.com/2017/09/06/linked-list/

Comments

0

If you have "good taste" you could probably appreciate this solution that relies on ref locals to mimic pointer magic.

public void Remove(T value) {

    ref var indirect = ref _head;
    
    while (indirect != null) {
        if (EqualityComparer<T>.Default.Equals(indirect.Value, value)) {
            indirect = indirect.Next;
            return;
        }
        indirect = ref indirect.Next;
    }
}

Comments

-1

In THEORY, you could do this to remove any random node from a single link list:

void RemoveNode(Node toRemove)
{
    toRemove.PointerToSomeValue = toRemove.NextNode.PointerToSomeValue ;
    toRemove.NextNode = toRemove.NextNode.NextNode ;

}

But, you need to be carefull about concurency issues. (ie. somebody else has a link to your node assuming it still caries the old value (an ABA problem) ), and you need to have a "marker" (empty) node at the end of the list, which you must never attempt to delete.(because of the toRemove.next.next)

Edit: obviously PointerToSomeValue is whatever data you want to keep in your list. And you're not actually deleting the node, you're basically removing the next node in the list, oh,well.. you get the ideea

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.