0

I'm trying out a simple program on linked list add in between and beginning.

#include<stdio.h>
#include<malloc.h>

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

/* Count the no of items in the list */
int count(struct node* q){
    int c = 0;
    while(q != NULL){
        q = q->link;
        c++;
    }
    return c;
}

/* Add a list at the last */
void append(struct node **q,int num){
    struct node *temp,*r;
    temp = *q;

    /* List is empty */
    if(temp == NULL){
        temp = malloc(sizeof(struct node));
        temp->data = num;
        temp->link = NULL;
        *q = temp;  
    }
    else{
        /* go to the last node */
        while(temp->link != NULL){
            temp = temp->link;
        }

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

/* add a node after the specific node */
void addafter(struct node *q,int loc,int num){
    struct node *temp,*r;
    int i;

    temp = q;

    /* Skip to the desired portion */
    for(i = 0; i < loc; i++){
        temp = temp->link;
        if(temp == NULL){
            printf("\n Few nodes - less nodes %d elements in list \n",loc);
            return;
        }
    }   

    /* insert new node */
    r = malloc(sizeof(struct node));
    r->data = num;
    r->link = temp->link;
    temp->link = r;
}

/* add a node at the beginning */
void addatbeg(struct node **q, int num){
    struct node *temp;

    /* add a new node */
    temp = malloc(sizeof(struct node));

    temp->data = num;
    temp->link = *q;
    *q = temp;
}

/* Delete a linked list */
void delete(struct node **q,int num){
    struct node *temp,*old;

    temp = *q;
    while(temp != NULL){
        if(temp->data == num){
            /* Node to be deleted is the first node */
            if(temp == *q){
                *q = temp->link;
                free(temp);
                return;
            }
            else{
            /* Delete the Intermdediate nodes */
            old->link = temp->link;
            free(temp);
            return;
            }
        }
        else{
            /* Traverse the linked list */
            old = temp;
            temp = temp->link;
        }
    }
}

/*  Display the data in the list */
void display(struct node *q){
    printf("\n");
    while(q != NULL){
        printf("\n Data : %d \n",q->data);
        q = q->link;
    }
}

int main(){
    struct node *p;
    p = NULL; /* Empty linked list */

    printf("\n No of items in linked list : %d\n",count(p));

    append(&p,100);
    append(&p,200);
    append(&p,300);
    append(&p,400);
    append(&p,500);
    append(&p,600);
    append(&p,700);
    append(&p,800);
    display(p);

    addatbeg(&p,10);
    addatbeg(&p,20);
    addatbeg(&p,30);
    display(p);

    addafter(p,0,1000);
    addafter(p,6,2000);
    addafter(p,9,3000);
    display(p);
    printf("\n No of items in the linked list : %d\n",count(p));

    delete(&p,800);
    delete(&p,500);
    display(p);

    printf("\n No of items in the linked list : %d\n",count(p));

    return 0;
}

I'm having a problem in the addafter(), In the function, we are creating another one copy of the pointer pointing to the heap and the changes made by the pointer will affect the pointer that is declared in the main as it is pointing to the same addressee of the heap. So I thought that I will do the same for the addatbeg(), when I changed ** to * , the changes were not reflecting. Why is it so ?. Anyways if addatbeg(struct node *,int num), then also the pointer is pointing to the same heap.

haccks
  • 104,019
  • 25
  • 176
  • 264
Angus
  • 12,133
  • 29
  • 96
  • 151
  • Because pointers are still passed by value. –  Oct 15 '13 at 09:25
  • Have a look on [whats-the-difference-between-passing-by-reference-vs-passing-by-value](http://stackoverflow.com/questions/373419/whats-the-difference-between-passing-by-reference-vs-passing-by-value) – Dayal rai Oct 15 '13 at 09:26
  • let me rephrase the question: why addatbeg() takes a * pointer and addafter() takes ** pointer. why addatbeg() doesnt take ** pointer and still it adds the node at the beginning? But If I make addafter() with a * pointer, Its not adding at the specified location. – Angus Oct 15 '13 at 09:33
  • @Angus Because in `main` you are calling `addatbeg` with `&p` as its argument but in `addafter` argument is just `p`. – Dayal rai Oct 15 '13 at 09:39

2 Answers2

2

The problem here is that p is defined in main() to be

struct node *p;

Now when you pass it to addatbeg(), you want the address that is stored at p to be changed because it will point to another node that has been added at the beginning of the list. However, when you use a definition like

addatbeg(struct node *,int num)

p is actually passed by value. In order to modify the p in main, you need to pass its address

addatbeg(struct node **,int num)

In addafter, you don't pass the address of p because you don't want your head pointer to change.

You can compare the situation to a simpler case. When you pass an integer by value you use foo(int), however when you want to modify the original integer you pass its address like foo(int *). The same thing is going on here with an extra level of dereferencing.

digital_revenant
  • 3,274
  • 1
  • 15
  • 24
1

you need ** as need the value contained by head pointer, which would contain the address to first node of the linked list. You are passing the address of a address so you need a double pointer

samairtimer
  • 826
  • 2
  • 12
  • 28