3

I was writing this code for adding element at the end of linked list:

struct node{
    int info;
    struct node* link;
};

void append ( struct node **q, int num )  
{

struct node *temp, *r ;

if ( *q == NULL )       // if the list is empty, create first node
{
    temp = (struct node*) malloc ( sizeof ( struct node ) ) ;
    temp -> info = num ;
    temp -> link = NULL ;
    *q = temp ;        
}
else{
    temp = *q ;         

    /* go to last node */
    while ( temp -> link != NULL )
        temp = temp -> link ;

    /* add node at the end */
    r = (struct node *)malloc ( sizeof ( struct node ) ) ;
    r -> info = num ;
    r -> link = NULL ;
    temp -> link = r ;
}
}

and I call append function like this: append(&list, 10); where list is the pointer to the linked list

This code works, but if I use single pointer in append function(using *q instead of **q) and make changes accordingly (as done below and also when I call it), it doesn't work. What is wrong with the code below?:

void append ( struct node *q, int num )  
{

struct node *temp, *r ;

if ( q == NULL )       // if the list is empty, create first node
{
    temp = (struct node*) malloc ( sizeof ( struct node ) ) ;
    temp -> info = num ;
    temp -> link = NULL ;
    q = temp ;        
}
else{
    temp = q ;         

    /* go to last node */
    while ( temp -> link != NULL )
        temp = temp -> link ;

    /* add node at the end */
    r = (struct node *)malloc ( sizeof ( struct node ) ) ;
    r -> info = num ;
    r -> link = NULL ;
    temp -> link = r ;
}
}
Robᵩ
  • 163,533
  • 20
  • 239
  • 308
Jatin
  • 14,112
  • 16
  • 49
  • 78
  • 1
    because C and C++ are closely related and I was assuming someone with the knowledge of C++ might be able to help me here. – Jatin Apr 06 '12 at 12:34
  • 1
    Incidentally, this is a bad approach to appending an element to the list, because the runtime increases linearly with the number of elements. The traditional approach is to maintain a pointer to both ends of the list, which allows appending to be done in constant time. – Oliver Charlesworth Apr 06 '12 at 12:49

2 Answers2

3

Because in the second example, q is a copy of the pointer passed in by the caller. The caller's original pointer never gets modified.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • But `list` is the pointer to a node. So, it stores an address. So, when I call `append(list, 10);` I am passing the address, so, shouldn't this change the original linked list. – Jatin Apr 06 '12 at 12:22
  • @Jatin: Not for the part of the code labelled "If the list is empty, create first node." – Oliver Charlesworth Apr 06 '12 at 12:27
  • So, assuming I have at least 1 element in the list, then the second code will work, right? – Jatin Apr 06 '12 at 12:29
  • and @Oli could you please elaborate on you last comment? – Jatin Apr 06 '12 at 12:41
  • @Jatin: The `if` section modifies the value of `q`, but this won't be reflected in the value that the caller passes in (because it's a copy). However, the `else` section doesn't do this, so this part probably works ok. – Oliver Charlesworth Apr 06 '12 at 12:43
1

In your first snippet (which is correct), you are doing too much.

void append ( struct node **q, int num )  
{

struct node *new ;

    /* go to last node */
    for ( ; *q; q = &(*q)->link ) {;}

    /* add node at the end */
    new = malloc ( sizeof *new );
    if (!new) { barf_now(); return; }

    new->info = num ;
    new->link = NULL ;
    *q = new; ;
    }
}

The basic idea is: you want to append to the tail of the list; you need to:

  • find the first NULL pointer
  • set it's value to the value of the new pointer

The "empty list" case is not special, it just means that you can find the NULL pointer in zero steps. Coding it this way there is no special case, and no need for an if (...) ... else ... construct.

wildplasser
  • 43,142
  • 8
  • 66
  • 109