Howdy, this blog post should explain what a linked list is and provide a Github link to my implementation of a linked list.
What is a linked list? It basically is a list of nodes, each node contains data(In my case a int32_t) and a pointer to the next node. Thanks to Wikipedia here is a visualization of what I mean
I also want to mention that the data which a node contains can be anything you wish. In my example I used a int because it is the quickest, additionally if you use for example a object as data, then you have to add the
bool operator==(const Object& other) const
{
return (importantVariable == other.importantVariable) && (moreImportantVariable == other.moreImportantVariable);
}
As already mentioned a linked list works with pointers to the next object (singly linked list), this means a linked list is not layed out in a continues block of memory but it is scattered across the memory unlike arrays which indeed live in a continues block of memory. This also means that the size of a linked list is variable and can be changed during runtime unlike a array.
The linked list starts with the head and grows in direction of the end. The head is always our starting point.
void insertNodeAtEnd( int32_t value )
{
Node* currNode = this;
// We iterate over the list to find the last node
while ( currNode->next != nullptr )
{
currNode = currNode->next;
}
// At this point we reached the end
Node* newNode = new Node( value );
currNode->next = newNode;
}
Node* insertNodeAtHead( int32_t value )
{
// We know that we have to add the new node at the beginning
// We just need to adjust the next element of the new node to point to
// the last head
Node* newNode = new Node( value );
newNode->next = this;
return newNode;
}
Node* deleteNode( int32_t value )
{
// If the head node contains the value we want to delete
if ( data == value )
{
Node* newHead = next;
delete this;
return newHead;
}
Node* currNode = this;
while ( currNode->next != nullptr )
{
if ( currNode->next->data == value )
{
// We save the address of the node which is to be deleted in tmp
Node* tmp = currNode->next;
// We adjust the next of the current node pointing to the node
// after the to be deleted one Basically we just skip the node
// in between
currNode->next = currNode->next->next;
delete tmp;
return this;
}
currNode = currNode->next;
}
return this;
}
This are the most important functions. The other functions I included in my code basically all work the same. Iterating and checking if next != nullptr.
I will add implementation and description of it later maybe.
// The 0th element would be the end
Node* getNthNodeFromEnd( int32_t n )
{
int32_t listLen = getSize();
if ( n > listLen )
{
std::cout << "N larger than size of linked list\n";
return nullptr;
}
int32_t nthElement = listLen - n;
Node* currNode = this;
// Starting at one because we are at the head alrady
for ( int32_t i = 1; i < nthElement; ++i )
{
currNode = currNode->next;
}
return currNode;
}
Node* getNthNodeFromEndDoublePointer( int32_t n )
{
if( n > getSize() )
{
std::cout << "N larger than size of linked list" << std::endl;
return nullptr;
}
Node* lazy = this;
Node* runner = lazy;
for( int32_t i = 0; i < n; ++i )
{
runner = runner->next;
}
while( runner->next != nullptr )
{
runner = runner->next;
lazy = lazy->next;
}
return lazy;
}