Milan
Milan

Reputation: 1529

Where head of this Link list points after recursive statement

I have simple link list program, that would create/print it, and later on print the last 2 number from it (in reverse order)

cat link_list.c 
/**
 * C program to create and traverse a Linked List
 */

#include <stdio.h>
#include <stdlib.h>

/* Structure of a node */
struct node {
    int data;          // Data 
    struct node *next; // Address 
}*head;


/* 
 * Functions to create and display list
 */
void createList(int n);
void traverseList();
void ReverseList(struct node *);


int main()
{
    int n;

    printf("Enter the total number of nodes: ");
    scanf("%d", &n);

    createList(n);

    printf("\nData in the list \n");
    traverseList();

    ReverseList(head);

    return 0;
}

/*
 * Create a list of n nodes
 */
void createList(int n)
{
    struct node *newNode, *temp;
    int data, i;

    head = (struct node *)malloc(sizeof(struct node));

    // Terminate if memory not allocated
    if(head == NULL)
    {
        printf("Unable to allocate memory.");
        exit(0);
    }


    // Input data of node from the user
    printf("Enter the data of node 1: ");
    scanf("%d", &data);

    head->data = data; // Link data field with data
    head->next = NULL; // Link address field to NULL


    // Create n - 1 nodes and add to list
    temp = head;
    for(i=2; i<=n; i++)
    {
        newNode = (struct node *)malloc(sizeof(struct node));

        /* If memory is not allocated for newNode */
        if(newNode == NULL)
        {
            printf("Unable to allocate memory.");
            break;
        }

        printf("Enter the data of node %d: ", i);
        scanf("%d", &data);

        newNode->data = data; // Link data field of newNode
        newNode->next = NULL; // Make sure new node points to NULL 

        temp->next = newNode; // Link previous node with newNode
        temp = temp->next;    // Make current node as previous node
    }
}


/*
 * Display entire list
 */
void traverseList()
{
    struct node *temp;

    // Return if list is empty 
    if(head == NULL)
    {
        printf("List is empty.");
        return;
    }
    
    temp = head;
    while(temp != NULL)
    {
        printf("Data = %d\n", temp->data); // Print data of current node
        temp = temp->next;                 // Move to next node
    }
}

static count=0, k=2;

ReverseList(struct node *head)
{
    if (head == NULL)
        return;
    else {
        ReverseList(head->next);
        count++;
        if (count <= k)
            printf("Data = %d\n", head->data);
    }
}

For an input 1 2 3 , it would first print 3 2 1 and then 3 2 correctly but I have confusion about the :

    if (head == NULL)
        return;

what exactly it returns with return;, and where head is pointing after the
ReverseList(head->next); statement ?

Upvotes: 1

Views: 104

Answers (2)

Vlad from Moscow
Vlad from Moscow

Reputation: 311068

For starters you forgot to specify the return type of the function in the function definition:

ReverseList(struct node *head)
{
    if (head == NULL)
        return;
    else {
        ReverseList(head->next);
        count++;
        if (count <= k)
            printf("Data = %d\n", head->data);
    }
} 

You have to write:

void ReverseList(struct node *head)

As for your question:

I have confusion about the :

if (head == NULL)
    return;

what exactly it returns with return;, and where head is pointing after the ReverseList(head->next); statement ?

Then as the function has the return type void and the return statement does not include an expression then the return statement returns nothing.

The function parameter head is a local variable of the function. The function does not change the pointer head declared in the file scope

struct node {
    int data;          // Data 
    struct node *next; // Address 
}*head;

In the first call of the function the parameter head has the value of the global variable head due to this statement:

 ReverseList(head);

If the value is not equal to NULL then the function recursively calls itself passing the value of the pointer head->next:

ReverseList(head->next);

So in the second recursive call of the function itself the value of its parameter head is equal to the value of head->next where in this expression head is the function parameter of the previous call of the function.

That is the parameter head at first gets the value of the global variable head and then the parameter is initialized sequentially by values of the data member next of the next node in the sequence.

So for the list that contains nodes with values 1, 2, 3 you have

1-st call parameter head is equal to the global variable head

2-nd call parameter head is equal to head->next that points to the node with the value 1

3-rd call parameter head is equal to head->next->next that points to the node with the value 2

4-th call parameter head is equal to head->next->next->next that points to the node with the value 3

5-th call parameter head is equal to head->next->next->next->next and equal to NULL

Pay attention to that it is not a good idea to use static global variables within the function

static count=0, k=2;

You need to remember reinitialize them if you want to call the function one more time. It is better to make the variable k a function parameter.

The function could be defined the following way as it is shown in the demonstrative program below.

#include <stdio.h>
#include <stdlib.h>

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

int push( struct node **head, int data )
{
    struct node *new_node = malloc( sizeof( *new_node ) );
    int success = new_node != NULL;
    
    if ( success )
    {
        new_node->data = data;
        new_node->next = *head;
        *head = new_node;
    }
    
    return success;
}

void display( const struct node *head )
{
    for ( ; head != NULL; head = head->next )
    {
        printf( "%d -> ", head->data );
    }
    
    puts( "null" );
}

size_t display_last_n( const struct node *head, size_t n )
{
    size_t i = 0;
    
    if ( head != NULL )
    {
        i = display_last_n( head->next, n ) + 1;
        
        if ( !( n < i ) )
        {
            if ( i != 1 ) printf( ", " );
            printf( "%d", head->data );
        }
    }
    
    return i;
}

void clear( struct node **head )
{
    while ( *head )
    {
        struct node *tmp = *head;
        *head = ( *head )->next;
        free( tmp );
    }
}

int main(void) 
{
    struct node *head = NULL;
    const int N = 10;
    
    for ( int n = N; n--; )
    {
        push( &head, n );
    }
    
    display( head );
    
    for ( size_t i = 0; i < N; i++ )
    {
        display_last_n( head, i + 1 );
        putchar( '\n' );
    }
    
    clear( &head );
    
    return 0;
}

The program output is:

0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> null
9
9, 8
9, 8, 7
9, 8, 7, 6
9, 8, 7, 6, 5
9, 8, 7, 6, 5, 4
9, 8, 7, 6, 5, 4, 3
9, 8, 7, 6, 5, 4, 3, 2
9, 8, 7, 6, 5, 4, 3, 2, 1
9, 8, 7, 6, 5, 4, 3, 2, 1, 0

Upvotes: 0

Some programmer dude
Some programmer dude

Reputation: 409374

Lets say we have a simple three-node list like this:

1 -> 2 -> 3

When we initially call ReverseList we pass the 1 node as the head and we have this call-chain:

ReverseList(1 -> 2 -> 3 -> NULL)
  ReverseList(2 -> 3 -> NULL)
    ReverseList(3 -> NULL)
      ReverseList(NULL)
    printf(3)
  printf(2)
printf(1)

Upvotes: 1

Related Questions