Saturday, 11 June 2011

Singly Linked List implemetation in C++


Single Linked List
A single linked list implementation in C++, the implementation is done in a header file. I have made use of templates to make the implementation data type independent. Leave your suggestions or doubts in the comments.

#ifndef LIST_HEADER
#define LIST_HEADER
#include <iostream>
#include <stdexcept>

class IllegalParameterValue: public logic_error {

public:
        IllegalParameterValue(const char reason[]);
};

template <class T>
struct ListNode {

        T element;
        ListNode<T>* next;

        ListNode() {}
        ListNode(const T& elelment)
        {
                this->element = element;
        }
        ListNode(const T& elelment, ListNode<T>* next)
        {
                this->element = elelment;
                this->next = next;
        }
};

template <class T>
class LinearList
{
        //Abstract class of the linear list.
        public:
                virtual ~LinearList() {}

                //virtual function : returns true is the list has no elements
                virtual bool empty() const = 0;

                //virtual function : returns the number of elements in the list
                virtual int size() const = 0;

                //Returns the refrence of the element at the index
                virtual T& elementAt(int index) = 0;

                //Returns the index of the first occurrence of the element
                virtual int indexOf(const T& element) = 0;

                //Removes the element at he index passed
                virtual void Erase(int index) = 0;

                //inserts the element at the given index
                virtual void insert(int index,T& element) = 0;

                //output the elements of the list
                virtual void output(ostream& out) const = 0;

};
template <class T>
class LinkedListSingle : public LinearList<T>
{
        protected:
                ListNode<T>* firstNode;
                int listSize;

        public:
                //constructor
                LinkedListSingle(int initialSize = 10);

                //copyConstructor
                LinkedListSingle(const LinkedListSingle<T>&);

                //destructor
                ~LinkedListSingle();


                //Implementations of Base class's Pure Virtual Functions : ADT Methods

                bool empty() const {return listSize == 0;}

                int size() const {return listSize;}

                T& elementAt(unsigned int index);

                int indexOf(const T& element);

                void Erase(unsigned int index);

                void insert(unsigned int index,T& element);
};

template <class T>
LinkedListSingle<T>::LinkedListSingle(int initialSize=10)
{
        if(initialSize < 1)
        {
                ostringstream s;
                s<<"The initial List size cannot be less than 1";
                throw logic_error(s.str());
        }

        firstNode = NULL;
        listSize = 0;
}

template <class T>
LinkedListSingle::LinkedListSingle(const LinkedListSingle<T>* theList)
{
        listSize = theList.listSize;

        //check if list is empty
        if(listSize == 0)
        {
                firstNode = NULL;
                return;
        }
        else
        {
                ListNode<T>* sourceNode = theList->firstNode;
                firstNode = new LinkedListSingle<T>(sourceNode->element);
                sourceNode = sourceNode->next;
                ListNode<T>* targetNode = firstNode;

                //copy all the elements from source list
                while(sourceNode != NULL)
                {
                        targetNode->next = new ListNode<T>(sourceNode->element);
                        targetNode = targetNode->next;
                        sourceNode=sourceNode->next;
                }
                targetNode->next = NULL;
        }

}

template <class T>
LinkedListSingle::~LinkedListSingle()
{
        while(firstNode != NULL)
        {
                ListNode<T>* nextNode = firstNode->next;
                delete firstNode;
                firstNode = nextNode;
        }
}

template <class T>
T& LinkedListSingle::elementAt(unsigned int index)
{
        if (listSize<index+1)
        {
                ostringstream s;
                s<<"The initial List size cannot be less than 1";
                throw logic_error(s.str());
        }
        else
        {
                ListNode<T>* nodeReturn = firstNode;
                int i = 0;
                for(i=0;i<index;i++)
                {
                        nodeReturn = nodeReturn->next;
                }
                return nodeReturn->elelment;
        }

}

template <class T>
int LinkedListSingle::indexOf(const T& element)
{
        if(listSize == 0)
        {
                return -1;
        }
        else
        {
                int i = 0;
                ListNode<T>* currentNode = firstNode;
                while(currentNode != NULL )
                {

                        if(currentNode->element == element)
                        {
                                return i;
                        }
                        currentNode = currentNode->next;
                        i++;
                }

                return -1;
        }
}

template<class T>
void LinkedListSingle::Erase(unsigned int index)
{
        if(listSize < index+1)
        {
                ostringstram s;
                s<<"The initial List size cannot be less than 1";
                throw logic_error(s.str());
        }
        else
        {
                ListNode<T>* currentNode = firstNode;
                if(index == 0)
                {
                        firstNode = currentNode->next;
                        delete currentNode;
                        listSize--;
                }
                else
                {
                        int i =1;
                        for(i=1;i<index;i++)
                        {
                                currentNode = currentNode->next;
                        }
                        ListNode<T>* toDeleteNode = currentNode->next;
                        currentNode->next = toDeleteNode->next;
                        delete toDeleteNode;
                        listSize--;
                }

        }
}

template<class T>
LinkedListSingle::insert(unsigned int index, const T& theElement)
{
        if(index >listSize)
        {
                ostringstream s;
                s<<"The initial List size cannot be less than 1";
                throw logic_error(s.str());
        }
        else
        {
                if(index == 0)
                {
                        firstNode = new ListNode<T>(theElement,firstNode);
                }
                else
                {
                        int i =1;
                        ListNode<T>* currentNode = firstNode;
                        for(i=1; i<index;i++)
                        {
                                currentNode=currentNode->next;
                        }
                        ListNode<T>* insertNode = new ListNode<T>(theElement,currentNode->next);
                        currentNode->next = insertNode;
                }
                listSize++;
        }
}
#endif