Deleting the only node of a linked list - c

I got a linked list with only one node. How do you remove that only node?
You can't "skip" it by pointing the *next struct of the previous struct to the next structure because there are no next structures, nor previous structures.
I've tried using free() but it didn't work either.
So the question is:
How do you remove the only node from a linked list? I've googled it, but no helpful links were found, unfortunately. Thank you for the help.

Because there are multiple ways in which linked lists are used, there's no single pattern which is best for every application. Nonetheless, a pattern which is very frequently helpful is to have one or two "special" and/or "pre-allocated" nodes which are used for the start and/or end of a linked list (sometimes it's helpful for doubly-linked lists to start and end with the same node; sometimes it's useful to have distinct "start" and "end" nodes). In a singly-linked list with one extra "start" node, the main reference to the list will typically identify the start node which will exist as long as the list does; that reference will never need to change. The fact that every "real" item in the list--even the very first one--will always have a node preceding it avoids the need to worry about special code to delete the first item or insert an item before it, since the first real item of the list may be treated just like any other.
Incidentally, when working with singly-linked lists, it is often a good idea to have each node contain a "deleted" flag. Generally in the process of finding a node, one will find the previous node as well; since deleting a node requires knowing which node preceded it, keeping track of the node which preceded a the most-recently-found node will often allow one to delete it without having to search for its predecessor. If, however, one finds multiple nodes and then performs actions upon them, it's possible that by the time one goes to perform an action on a node (e.g. deleting it), the node which used to precede it might no longer do so. Having a "deleted" flag in each node may make it easier to detect such conditions and handle them smoothly (if wants to delete a node and can't immediately identify the previous node, it may be best to simply set the "deleted" flag; if the invalidated node is later encountered by code which knows which node precedes it, that code can take care of actually removing the invalidated node from the list.

Assuming you have
struct foo * head;
somewhere which actually does point at your node, you should be able to
free(head);
If you can't, then you should post your code so that we can look at what you're actually doing wrong.

If you have the lasting node, then the head is that node. So, after you free(head) , make sure to declare head = NULL . This a good practice as long as I understand.
And, let's say you have a function to delete nodes. At the beginning, don't forget to code
if (*head == NULL)
return ("your error code");
This way, the programm won't try to free something that hasn't been allocated and get you a segmentation fault.

Related

Search in flat array based double link list when element in between head and tail

I have a double link list using arrays and while inserting elements I maintain order, something like this. I am treating new values (nodes) as array indices and store them directly to their location. The link list is quite long. Everything is working as required but is there any algorithm or ideas that can help me to reduce number of iterations when a node falls between head and tail?
That is
if (new_node > head && new_node < tail) {
search from head()
}
So to reduce iteration; I added search from tail() after finding new-node is closer to which head or tail. Then I added a mid-node that is somewhere in mid of head and tail. But still I am still not able to reduce iterations when node needs to be linked. Will knowing range of values help? What else can be done to reduce number of iteration while inserting (due to sorted nature)?
I hope I am able to explain this properly.
Here is a SO answer discussing the difference between array and linked list: insert/delete functions.
tldr; It is a limitation of double linked lists. Even if you wrap it inside an array to do stuff.
Understanding the underlying methods of how a linked list and array works will help identify the impossible issue you are solving. Unless you utilize a different structure, you will typically have the issues you are describing.
I would do the following:
Consider your problem, what do you CARE about
Searching?
Insert/Delete?
Memory size?
Then decide a data structure that best solves your problem
Array
Linked List
Trees
Hash

Easiest node to remove from a LinkedList

May I know if there is anything like the easiest node to be removed or deleted from a LinkedList.
I know that deleting a node from in between requires a change of the preceding nodes link, whereas deleting from beginning needs a change of pointer to the new head and deleting from the end needs a change of new end of the list.
But, if asked to delete a node from the LinkedList which is easier which of these should be preferred?
Sounds like you are on the right track with your thoughts on linked lists. Another thing to consider about removing the easiest node from a linked list is the following:
How often will these easiest nodes be removed? If the node is removed from the head of the list the removal will be complete in O(1) time, but if the easiest nodes are at the rear of the list removal will take a full traversal of the list completing in O(n) time.

Linked List - Appending node: loop or pointer?

I am writing a linked list datatype and as such I currently have the standard head pointer which references the first item, and then a next pointer for each element that points to the following one such that the final element has next = NULL.
I am just curious what the pros/cons or best practices are for keeping track of the last node. I could have a 'tail' pointer which always points to the last node making it easy to append, or I could loop over the list starting from the head pointer to find the last node when I want to append. Which method is better?
It is usually a good idea to store the tail. If we think about the complexity of adding an item at the end (if this is an operation you commonly do) it will be O(n) time to search for the tail, or O(1) if you store it.
Another option you can consider is to make your list doubly linked. This way when you want to delete the end of the list, by storing tail you can delete nodes in O(1) time. But this will incur an extra pointer to be stored per element of your list (not expensive, but it adds up, and should be a consideration for memory constrained systems).
In the end, it is all about the operations you need to do. If you never add or delete or operate from the end of your list, there is no reason to do this. I recommend analyzing the complexity of your most common operations and base your decision on that.
Depends on how often you need to find the last node, but in general it is best to have a tail pointer.
There's very little cost to just keeping and updating a tail pointer, but you have to remember to update it! If you can keep it updated, then it will make append operations much faster (O(1) instead of O(n)). So, if you usually add elements to the end of the list, then you should absolutely create and maintain a tail pointer.
If you have a doubly linked list, where every element contains a pointer both to the next and prev elements, then a tail pointer is almost universally used.
On the other hand, if this is a sorted list, then you won't be appending to the end, so the tail pointer would never be used. Still, keeping the pointer around is a good idea, just in case you decide you need it in the future.

Mid point in a link list in a single traversal?

I'm trying to find the point of a singly link list where a loop begins.
what I thought of was taking 2 pointers *slow, *fast one moving with twice the speed of other.
If the list has a loop then at some point
5-6-7-8
| |
1-2-3-4-7-7
slow=fast
Can there be another elegant solution so that the list is traversed only once?
Your idea of using two walkers, one at twice the speed of the other would work, however the more fundamental question this raises is are you picking an appropriate data structure? You should ask yourself if you really need to find the midpoint, and if so, what other structures might be better suited to achieve this in O(1) (constant) time? An array would certainly provide you with much better performance for the midpoint of a collection, but has other operations which are slower. Without knowing the rest of the context I can't make any other suggestion, but I would suggest reviewing your requirements.
I am assuming this was some kind of interview question.
If your list has a loop, then to do it in a single traversal, you will need to mark the nodes as visited as your fast walker goes through the list. When the fast walker encounters NULL or an already visited node, the iteration can end, and your slow walker is at the midpoint.
There are many ways to mark the node as visited, but an external map or set could be used. If you mark the node directly in the node itself, this would necessitate another traversal to clean up the mark.
Edit: So this is not about finding the midpoint, but about loop detection without revisiting already visited nodes. Marking works for that as well. Just traverse the list and mark the nodes. If you hit NULL, no loop. If you hit a visited node, there is a loop. If the mark includes a counter as well, you even know where the loop starts.
I'm assuming that this singly linked list is ending with NULL. In this case, slow pointer and fast pointer will work. Because fast pointer is double at speed of slow one, if fast pointer reaches end of list slow pointer should be at middle of it.

Find the last node of a circular linked list whose size is unknown and the last node points to any other node except first node of the linked list

How can I find last node of a circular linked list whose size I don't know and the last node points to any other node except first node of the linked list?
One algorithm that can be used for this is the Floyd cycle algorithm.
Also, see this question.
By definition, if a node does not point to the first node of a circular linked list,
it is not the last node.
Can you elaborate here?
A strange list... why would you ever need something like this? But anyway...
You can simply iterate over all nodes, and stop as soon as the next node would be one you have already visited. The current node will then be your answer.
You need some way to keep track of which nodes have been visited. Add a boolean flag to each node, or use some kind of set data type with fast insertion and lookup (e.g. a hash set).
Maybe add parameter to nodes of the list which tells you if you at end? I think, it wouldn't be problem.
Otherwise, you can remember nodes you already visted. When the next node is already visited, you are at the end.
The Floyd cycle algorithm won't give the last element of the list. It will only tell if there is a cycle or not.
The definition of the last one would be that, while traversing the list in a sequential scan starting from the first one, all elements before it and the last one aren't seen before (pointer value). The after last one will be the first element that has already been seen in this sequential scan.
An easy solution is to flag visited elements so an element already seen is easily detected. The flag may be intrusive, i.e. by changing a bit in the element, or external by using a hash table to store pointer values.
Since we need to be able to test if an element has already been visited, I don't see another solution.
I can elaborate on how to use Floyd's algorithm to solve this problem but I don't understand the explanation for one step
Have 2 pointers traverse the linked list, pointer 1 going at a rate of 1 node per iteration, the second going at a rate of 2 nodes
When the pointers meet, we are in the cycle and we are some distance before pointer 1 has reached the end of the cycle (we know pointer 1 hasn't reached then end because if cycle is distance d and pointer 2 is going at twice the speed of 1, pointer1 will loop the cycle twice before pointer 1 does it once)
So because they have met before pointer 1 fully traversed the cycle, we know that the meeting point is d nodes from the start and k nodes within the cycle (pos = d + k)
If we set pointer 1 to position 0 and start both points again (but at the same rate rate of 1 node per iteration), they will meet at the start of the cycle.
Since we know the start of the cycle, finding the end is trivial
I don't fully understand why step 4 is true but I had a friend explain the solution to me.

Resources