Linked List insert in C - c

I have recently started working with linked lists. To push an element into linked list in the insert(...) function, I saw we always check if(head == NULL) but it occurs only once.
I want to know if there is any way so that we can avoid the unnecessary check always. Please suggest something that would be relevant to most of the linked list operations. One solution I figured out is that writing a new function "add_first_element(....)" so that explicitly we add the first element and then other elements are added in a generic way.
I am looking for a better solution.

A common way is to use a sentinel node. That is, a node that contains no useful data, but merely serves as the placeholder for the one before the first node. This way you don't need to check for null.
For double-linked list, you will need two sentinel nodes to avoid null checking.

Related

Inserting an item to a linked list - is iteration necessary (C)?

I'm currently studying linked lists for interview prep, would appreciate if anybody could shed some light on this. The following function in C supposedly inserts a new element into the list after a certain Element elem (passed as an argument to the function):
bool insertAfter(Element * elem, int data){
Element * newElem, * curPos = head;
newElem->data = data;
while(curPos){
if(curPos == elem){
newElem->next = curPos->next;
curPos->next = newElem;
return true;
}
curPos = curPos->Next;
}
return false;
}
Although the above is specified in the textbook I am studying from, I tried coming up with a solution that does not use any iteration whatsoever:
bool insertAfter(Element * elem, int data){
Element * newElem;
newElem->next = elem->next
newElem->data = data
elem->next = newElem;
return true;
}
However, as it appears too simplistic, I sense that it may not work, but am not sure why. I need some insights on the technicalities on why this may or may not work, thanks.
Both versions suffer from the error of using newElem as though it were a valid pointer. It is not. It is not initialized to point to valid object.
You can correct that by allocating memory for an object before using:
Element * newElem = malloc(sizeof(*newElem));
The difference between the two versions is that if elem is not accessible from head for some reason or it is NULL, the first version will do nothing to the existing list. The second version does not deal with either of those scenarios. It assumes that elem is in the list and that it is not NULL.
Your solution is pretty much correct. The iteration in the example is almost completely useless.
What the example function is doing is: given an element to insert the new data after, it looks through the list starting with head to find that same element, then inserts the data - doing nothing with head or elem after finding it. Since all the loop does is "find" an element to which you already had a pointer, it essentially did nothing at all and is useless.
The only possible use of this is to constrain the insertion function to only work on this one list beginning with head, globally, throughout your program. This is such a strange design decision that one would likely assume it's a mistake unless given a reason to believe otherwise (dynamic data structures constrained to a single instance are an unusual pattern; more importantly, the whole point of linked lists is O(1) insertion, which the example function breaks by adding this useless loop). head is not needed for any other reason than to enforce this constraint, and if this is desired, it would make more sense to pass it in as a parameter as well so that the function is able to be used on more than one list per-program. (Or, not to perform the check at all: another use of linked lists is that you can pass around and insert after nodes without worrying about the head element.)
As other people have pointed out, you fail to actually allocate newElem, but so does the textbook. Overall, it's a rubbish example; not only did the author make a mistake with allocation, but they don't appear to understand the basic advantages of using linked lists. You should definitely treat this textbook with suspicion.
Your logic will work, because you just need a pointer to a node where you want to insert a node. If you already have such a pointer, no need to iterate and search for the node.
However the search (iteration) would be relevant if do not have in hand the node pointer where you want to insert the new node. Example: suppose the nodes have unique keys and you do not have the node pointer where the key exists and you want to insert after you find the node containing the specific key, then you need to find the correct node pointer and do the insertion (The function should then take in key as the argument).
However in your code (both cases), you have not allocated the memory for the new node. You need to do malloc for the new node and then go on with the insertion.
This will not work because you do not know your newElem. In linked list you have knowledge about a head and each element gives you information where to find the next one:
head -> e1 -> e2 -> ...
So you need to iterate till you will find the element you care about. But you can also iterate with the recursion.

Removing elements from a linked list

I'm refactoring some C code and since a while i'm hanging up with a problem related with a linked list data structure. Please have a look at the following simplified snippet:
Link apply(Link first, pred_ptr cond)
{
Link t=first->next,p=first;
do{
if(cond(t))
{
p->next=t->next;
free(t);
t=p;
}
p=t;
t=t->next;
}while(t!=first);
//Check the first
if(cond(first))
{
t=first->next;
free(first);
first=t;
p->next=t;
}
return first;
}
The function apply remove all the elements from the linked list for which the function cond return a non-zero value. Link is something like this:
struct node
{
struct node* next;
//Stuff
};
typedef struct node* Link
Well, the only question i have is about how apply remove the very first element of the linked list -first-, looks like the extra code out of the loop is required in order to valuate the first element, i was not able to put this check inside the loop without extra if statements, perhaps you may know how to remove the extra code from the loop -if possible-, do you?
Thanks,
Have a nice day.
The first element is a special case so it is unsurprising that you will have code for that one that is slightly different from every other case. So your alternatives are (1) the way it is done in your example, (2) putting the special case code in the main loop with an if comparison executed every iteration, or (3) a less understandable version using pointers to pointers.
The first question you should ask yourself is: Why are you refactoring? For clarity or because there is a demonstrated need for a faster implementation? Or ...?
Your code have the logic almost right but have various problems in some places:
Reading the code, I guess that the link list is really a circular link list, because if not, some ->next would be == NULL in some node. And the code don't check for NULL in any place, lines like t=t->next; before the while loop end will execute Undefined Behavior when NULL is reached. Assuming that cond function work OK with NULL and not enter the if statement (if enter, the UB would be executed here p->next=t->next;). If the link list is only a link list and not circular, the code need a lot of refactoring.
The first element in either way linked list or circular linked list could be analyzed separately, in the case of simple linked list it's better this way, because the loop analyzing the rest of the nodes is more readable and free of handling specific cases (would be handled out of the loop, and you won't overload the analyze of the other node with checking for the first node), in the case of circular linked list the first element could be analyzed in the loop elegantly but can be analyzed out the loop too.
By the way that you are already in the refactoring if this are the variable names used in the actual code would be better improved (p -> previous, t -> test? i think, etc...)

Linked List Implementation Options in C

In implementing a single linked list in C, I think there are three ways :
HEADER IS A POINTER ITSELF.IT POINTS TO THE FIRST NODE OF THE LINKED LIST.
1.Declare the header globally and use function void insert(int) to insert.This should work as header is global.
2.Declare header inside main and use function node*insert(node*) to insert.This should work because of the return involved.
3.Declare header inside main and use function void insert(node**) to insert.
Sometimes the second way works even without the return involved. Why?
Which is the better way?
If the functions involved are recursive as in tree which method is appropriate?
You should encapsulate your data structure in a single object (the head node or a struct that contains it), and then you can have your functions work on that object. This means that you can have more than one linked list in your program (that won't work with a global head node) and you can also pass it around to different functions that want to use it (there's no point having a data structure without being able to use it).
If you have your single object (head node) stored in your program then the insert and delete functions don't need to return anything, as you already have a pointer to the object that represents the linked list.
If the functions involved are recursive as in tree which method is appropriate?
The functions should not be recursive "as in tree". The depth of a tree is O(logn), which means recursion is reasonable in many situations; The size of a linked list is O(n), which means recursion can easily overflow the stack.

Losing parts in Link List in C

I'm trying to make a link list and I'm having trouble with the concept with linking the middle part, I'm just doing a little pseudo-code right now, haven't actually coded anything.
(struct pointers) *current, *ahead, *behind, *begin;
(behind)-->(current)-->(ahead) //This is what I want to do
behind->next = current;
current->next = ahead;
Is this the proper way to break and connect the list? Without losing anything..
What you have looks correct but rather incomplete. One of the unwritten rules of programming is that you cannot write a linked list implementation correctly the first time. There are four cases you need to deal with:
Insert into an empty list
Insert into a non-empty list
Removing the first element from the list
Removing any other element from the list
There are also doubly-linked lists, where each element has a pointer to both the previous element and the next element. That makes it easier to handle things like removal of a random element without traversing the list, but can be trickier to get right.

please can some one help me explain linked list?

I have tried a lot to learn linked list.But all my efforts were wasted.Please can some one help me understand linked list by providing his/her own code?Thanks in advance.
A linked list is simply a list of elements (usually called nodes) where each node has a reference (or pointers, in C) to the next node:
http://img837.imageshack.us/img837/5613/ll1s.png
You keep track of the list by having a pointer to the first node (the "head"), and by having the last node point to null
Linked lists where each element points to both the next and previous nodes are called doubly-linked lists.
By following these references, you can traverse the list and get any node.
A common advantage of linked lists over arrays is that you can insert and remove the elements in O(1) (constant) time. The disadvantage is that you have O(N) random-access.
See Wikipedia for more.
Have you play some of these rally games? The organizer left this hints all around the city and you must get one hint and then solve the riddle for getting the position of the next hint. Now, imagine every hint comes with a little prize.
Well, linked list are like that: every element has "content" on it AND the memory address (the hint) for getting the next item. The next item, of course, has another prize and another hint.
A linked list is a series of object each pointing to the next one in the list. The last element in the list has NULL as it's next pointer.
You keep track of the head of the list in your program so you can traverse the list from the start.
You might want to keep track of the current position in the list, but that will depend on your application.
A doubly linked list has a previous element pointer too enabling you to traverse the list in both directions.
This:
typedef struct tagProp
{
rtPropertyKey key;
rtProperty property;
struct tagProp *next;
} TProperty;
defines a property key/value lookup list.
A linked list is implemented as a list of "nodes". The nodes are linked together using pointers. The following code describes one node. The pointer to the next node is called next. In my example, each node contains an integer value as its data.
struct node {
int val;
struct node * next;
};
The fun is how to actually create a list. You have to use malloc to create new nodes. When you malloc the new node, you have to tie into the list using the next pointer.
We can help you more if you specifically tell us what your issues are...

Resources