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.
Related
Can anyone help me with finding an algorithm to change a position of a node in a linked list according to the input?
Example:
I have the linked list: 1->2->3->4->END and the user chose the second node and the index 4.
The algorithm will give us the result:
1->3->4->2->END.
Thanks for your help!
It is really easy to move nodes in a linked list because they are done for that...
To change a node's position, just change it's next pointer to the next node address, and the previous node's next pointer to the node you want to move and that's done.
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.
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.
given a singly linked list, how to determine head node from a specified node (for e.g say node 4).total # of nodes: 10.Thanks. Logic will do,code is appreciated.
We know given a head node one can perform a forward traverse and determine next node easily.
For this case, use of doubly linked list would be simpler but i was wondering if it is possible to track down head node using singly linked list.Thanks.
Its not possible at all to do that with the kind of singly linked list you've described.
Your question isn't entirely clear. But the only way this is possible is if each of your candidates is the head of a unique list, and one of them is the head that you're after.
For each candidate, traverse the list that starts from it. You will eventually hit the corresponding tail, or you will hit the node in question.
You can also make this work even if your set of candidates are not all heads of unique lists. But you would need logic to detect overlap.
You simply cannot in the singly linked list.
From Wikipedia :
Singly linked lists contain nodes which have a data field as well as a
'next' field, which points to the next node in line of nodes.
You cannot go back to the previous node as you don't have any information about it. If you were given any random node of a singly linked list, the head of your new list will be that node, as you cannot go back any further.
I am creating a student list (linked list) that can add, view and edit student information. I have two fields namely Student Name and Student Grade and I add new students in the list in a way that it is sorted according to the student's grades in descending order.
I have finished doing the add and view portion. The problem is on the edit part because I need to edit the information, then I need to sort it again so that it would be on the proper location of the list.
For example, I have 3 students information arranged according to their grades:
student1 90 -> student2 85 -> student3 80 -> NULL
Then I need to edit student2's grade to 75 so the edited linked list should now be arranged as follows:
student1 90 -> student3 80 -> student2 75 -> NULL
How should I do that? You don't need to give me any code. I just want some advices on how I can implement the edit part of my program. I am thinking of creating a new node (with the edited info), delete the old node and insert the edited node into the list. Is my logic correct? or is there a better way on solving my problem.
You can accomplish your goal by
Removing target node
Editing target node data
Reinsert the node using your existing logic for inserting nodes.
Singly linked list?
Find the node you want to edit, and either keep a pointer to the previous node or write a routine to retrieve the previous node.
Remove your node from the linked list (by setting previous_node->next to thisOne->next)
Make your edits.
Insert the new node in the right place in the list (by traversing the list unti the next node is less than your edited value.
Splice edited into the list ( editedNode->next = nextNode; current->next = editedNode)
With doubly linked lists you can just use the "other"/back/up link to find the previous node
Basically your idea is correct except that I wouldn't create a new node. What I would do would be:
Identify if value has increased or decreased (and update node).
Unlink node from the list.
Search forwards or backwards (depending on increase or decrease of grade) for correct location.
Link node into new location.
Note that indexing the list into an array, etc. may give a quicker search than a linear traversal. If you already have such a mechanism it may be quicker to use that when finding the location to re-insert the node.
You could do a function that edits a specified node. Scan the list until you find that node and then directly edit it. Of course you will use a pointer. For the sorting part, say you have n nodes, compare every node i with the nodes after it and swap them if the one you are comparing with is larger:
for every node n1 in list
for every remaining node n2 in list
if n2->grade > n1->grade
swap 'em
you can swap them copying their memory, so you won't need to change any pointer.