views:

103

answers:

3

What will be the complexity of the operation to remove an element from the end of the singly linked list ? I have implemented linked-list in C. Here is the code for removing a element from the end of linked-list. Now my query is that how to calculate the complexity of this snippet. What are the factors involved. There are other operations involved too like

  1. Insert at begin
  2. Insert at middle
  3. Insert at end
  4. Delete at begin ,middle ,end
  5. Reverse the list

How will I be able to calculate them ?

struct node {
       int val;
       struct node * next;
    };

    typedef struct node item;
    item * head = NULL;

 /* DELETION AT THE END OF THE LIST */     
        deleteatend() {
        item * temp, * curr;
        if(head == NULL) {
            printf("\n Linked list is Empty ");
            return;
          }
        temp = head;
        if(head->next == NULL) { /* When There is atleast 1 NODE */
            head=NULL;
         } 
        else {
            while(temp->next != NULL) { /* Traversing the list upto second-last NODE */ 
              curr=temp;
              temp=temp->next;
              } 
            curr->next =NULL;  /* When TEMP points to last NODE */ 
        }
        free(temp);
       }    

code for Reverse the list :

 /* Reverse Printing of list */
      reverselist() {
          item * curr, * nextnode, * prev;
          curr = head;
          nextnode = curr-> next; /* NEXTNODE traverses till the end of the list */
          prev = NULL;
          curr-> next = NULL; /* Making the first Node as Last node */
          while(nextnode != NULL) {
            prev = curr; /* Generally holding the last element of the reversed list */
            curr = nextnode; 
            nextnode = curr-> next;
            curr-> next = prev;
           } /* End of WHILE */
          head = curr;
        }  
A: 

The complexity of a plain linked list operation is constant if it is implemented without a loop or recursion and linear if is implemented with a loop.

Peter G.
I see, then it follows that reverselist() is not your code, because it contains a while() loop.
Peter G.
Still, I made the omission of recursion. I've added that now in the answer.
Peter G.
@Peter G.: I am sorry, I just overlooked it.
Tuhin
@Tubin deleteAtEnd() also contains a loop: while(temp->next != NULL)
Peter G.
@Peter G.: If you think i can send you the total code right now and explain you what i have done in each line, its not copied from any where.please believe it
Tuhin
A: 

With a list it is linear to length of the list, so Θ(n), while direct access, like an array is Θ(1).

kuroutadori
@kuroutadori: Here as you can see i have implemented using pointers, I think my code complexity will be of the O(1) .If i am not wrong
Tuhin
It is a proper list, you have to go through all elements of the list to get to the end. So it's linear Θ(n). What I ment by direct access is with an array, it adjust the head pointer of the array to get the element in the array, so it's constant Θ(1)
kuroutadori
@kuroutadori:But what about my Reverse the list code ?
Tuhin
It will be linear, as it has to go through each element.
kuroutadori
@kuroutadori: Thanks !
Tuhin
@kuroutadori: If there are two while/for loop in a snippet what will the complexity ?
Tuhin
@Tuhin if you have two separate loop, then it would be Θ(2n). If they are nested into each other it will then be Θ(n^2).
kuroutadori
+4  A: 

I will give some kitchen recipes to find out the (apparent) complexity of an algorithm. It is not mathematically rigorous, for that you will have to consult your schoolbooks.

  1. Find the parameters on which your analysed code depends. N for number of elements of your list. Other algos have other parameters, number of characters, number of elements in an array.

  2. Find the loops. See on what parameter they depend on.

    1. To insert the first element of a list you don't need to loop, so it's the same operation if your list contains 1 or 1 billion elements.

    2. To insert in the middle you have to loop once completely through the list and depending on how you implement it, you have to loop a second time to the middle, so you have 1.5 times N iterations. The complexity depends only on the length of the list, its complexity is therefore O(N). If you implement it by only looping once, you will have N iterations and still complexity O(N). The choice of which way to implement it may depend on the individual time of each iteration (and the time to implement it).

    3. Same as above, you have to go through the entire list once, so complexity O(N).

    4. Same as for insert.

    5. To reverse the list, you need only to loop once over the list so again complexity O(N).

    6. Just for the example of another complexity. If you want to eliminate all double entries of your list. You have to check for every element if it is equal to any other element of the list, this means you have to loop through all elements, take the element and compare it to every other element in the list. In the worst case no doubles are in the list meaning the list doesn't shrink so you tend to have N*(N-1) comparisons. In O notation O(N*(N-1)) = O(N²-N) dominates so we have a complexity of O(N²) a quadratic algorithm.

PS: I wrote at the beginning apparent because sometimes there are terms depending on N that are not visible in the program itself but are part of the abstraction you're working on. In the case of your list, if it gets so big that your system starts swapping, you hit one of those hidden terms of the real complexity, one that was burried in the virtual memory abstraction of your operating system.

tristopia
@ tristopia: Thanks for giving the extra effort and explain the cases separately !But this part "I wrote at the beginning apparent because sometimes there are terms depending on N that are not visible in the program itself but are part of the abstraction you're working on." I didn't understood ?
Tuhin
What I ment with that is, that your program works on a machine that is abstract. This means your operating system gives your program the impression that it is alone on the machine or that it has infinite memory. But in reality it is not the case, so if you build a list of 10 billion elements, you will hit the limits of your operating system (cache thrashing, memory swapping etc.). This will slow down your program tremendously and the effect is dependend of the N of your program. Continued below.
tristopia
In a normal programing class this effect can be ignored. On a real machine, with real programs the effect can be huge.
tristopia