Search code examples
c++linked-listsingly-linked-listdouble-pointerfunction-definition

How to make linked list with localy declared head?


I need to make a program which connects two linked lists before I used global pointer for the head of the list, but now I need to make it locally so I can insert new element(node) to each of them, but I have a problem with double-pointer, not sure when to use **, when * and when &. I can find any example similar to that. Down below is what I have now.

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

typedef struct element_{
    int x;
    struct element_ *next;
}element;


void insert(element **head, int x) {
    element *new_ = new element;
    element *p;
    new_->x = x;
    new_->next = NULL;

    if (head == NULL) {
        *head = new_;
        return;
    }
    else {
        for (p = *head;p->next != NULL;p = p->next) {}
        p->next = new_;
    }

}


int main(){
    element **head = NULL;

    insert(head,1);
    insert(head,3);
    insert(head,3);
    insert(head,4);

    for (element *p = *head;p != NULL;p = p->next){
        printf("%d ", p->x);
    }


}

Solution

  • There is nothing from C++ in the program except the operator new. So if to substitute the operator new for a call of malloc then you will get a pure C program.

    So a C looking function insert can be defined like

    void insert(element **head, int x) 
    {
        element *new_ = new element;
    
        new_->x = x;
        new_->next = NULL;
    
        while ( *head != NULL )
        {
            head = &( *head )->next;
        }
    
        *head = new_;
    }
    

    And in main you should write

    element *head = NULL;
    
    insert( &head, 1 );
    insert( &head, 3 );
    insert( &head, 3 );
    insert( &head, 4 );
    
    for (element *p = head; p != NULL; p = p->next )
    {
        printf("%d ", p->x);
    }
    

    Something that looks like a C++ function insert can be defined the following way

    void insert( element * &head, int x ) 
    {
        element *new_ = new element { x, nullptr };
    
        element **current = &head;
    
        while ( *current != NULL )
        {
            current = &( *current )->next;
        }
    
        *current = new_;
    }
    

    And in main you should write

    element *head = nullptr;
    
    insert( head, 1 );
    insert( head, 3 );
    insert( head, 3 );
    insert( head, 4 );
    
    for (element *p = head; p != nullptr; p = p->next )
    {
        std::cout << p->x << ' ';
    }
    

    But to call the program indeed as C++ program then you should define the list as a class. Moreover if new nodes are appended to the tail of the singly-linked list then you should define the list a singly-linked two-sided list.

    Here is a demonstrative program.

    #include <iostream>
    #include <functional>
    
    class List
    {
    private:    
        struct Node
        {
            int data;
            Node *next;
        } *head = nullptr, *tail = nullptr;
    
    public:
        List() = default;
        List( const List & ) = delete;
        List & operator =( const List & ) = delete;
        ~List()
        {
            clear();
        }
    
        void clear()
        {
            while ( head )
            {
                delete std::exchange( head, head->next );
            }
    
            tail = head;
        }
    
        void  push_front( int data ) 
        {
            head = new Node { data, head };
            if ( !tail ) tail = head;
        }       
    
        void  push_back( int data ) 
        {
            Node *node = new Node { data, nullptr };
    
            if ( tail )
            {
                tail = tail->next = node;
            }
            else
            {
                head = tail = node;
            }
        }       
    
        friend std::ostream & operator <<( std::ostream &os, const List &list )
        {
            for ( Node *current = list.head; current; current = current->next )
            {
                std::cout << current->data << " -> ";
            }
    
            return std::cout << "null";
        }
    };
    
    
    int main()
    {
        List list;
    
        list.push_back( 1 );
        list.push_back( 3 );
        list.push_back( 3 );
        list.push_back( 4 );
    
        std::cout << list << '\n';
    } 
    

    Its output is

    1 -> 3 -> 3 -> 4 -> null