Last active
October 7, 2019 17:00
-
-
Save chrisengelsma/7d29883148f7421d58b7965a0f895a75 to your computer and use it in GitHub Desktop.
C++17 Linked List Implementation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @class LinkedList | |
* @brief A simple linked list. | |
* | |
* A linked list is a data structure represented by a series of nodes wherein | |
* each node maintains a record of its stored value and a pointer to another | |
* node. | |
* | |
* This implementation is intended to provide very basic functionality, | |
* including insertion, deletion, and size. | |
* | |
* @author Chris Engelsma <[email protected]> | |
* @date Oct 7, 2019 | |
*/ | |
#pragma once | |
#include <iostream> | |
#include <sstream> | |
template<typename T> | |
struct Node | |
{ | |
T data; | |
Node* next; | |
}; | |
template<typename T> | |
class LinkedList | |
{ | |
public: | |
// The head node. | |
Node<T>* m_head{nullptr}; | |
/** | |
* @brief Constructs an empty linked list. | |
*/ | |
constexpr LinkedList() = default; | |
/** | |
* @brief Destructs this linked list. | |
*/ | |
~LinkedList(); | |
/** | |
* @brief Returns this linked list as a space-delimited std::string. | |
* @return a std::string representation of this list. | |
*/ | |
[[nodiscard]] std::string toString() const; | |
/** | |
* @brief Inserts a value at the beginning of this list. | |
* @param value a node value to insert. | |
*/ | |
template<typename K> | |
constexpr void insertFirst(const K& value); | |
void insertFirst(const T& value); | |
/** | |
* @brief Inserts a value at the end of this list. | |
* @param value a node value to insert. | |
*/ | |
template<typename K> | |
constexpr void insertLast(const K& value); | |
void insertLast(const T& value); | |
/** | |
* @brief Removes the first value from this list. | |
*/ | |
void removeFirst(); | |
/** | |
* @brief Determines if this linked list is empty. | |
* @return true, if empty; false, otherwise. | |
*/ | |
[[nodiscard]] bool isEmpty() const { return m_head == nullptr; }; | |
/** | |
* @brief Removes the last value from this list. | |
*/ | |
void removeLast(); | |
/** | |
* @brief Gets the number of nodes in this list. | |
* @return the number of nodes in this list. | |
*/ | |
[[nodiscard]] size_t size() const; | |
friend std::ostream& operator<<(std::ostream& stream, const LinkedList& list) | |
{ | |
stream << list.toString(); | |
return stream; | |
} | |
}; | |
using LinkedListf = LinkedList<float>; | |
using LinkedListd = LinkedList<double>; | |
using LinkedListi = LinkedList<int32_t>; | |
using LinkedListui = LinkedList<uint32_t>; | |
#include "LinkedList.inl" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "LinkedList.h" | |
template<typename T> | |
LinkedList<T>::~LinkedList() | |
{ | |
if (m_head != nullptr) | |
{ | |
auto node = m_head->next; | |
while (node != nullptr) | |
{ | |
auto next = node->next; | |
delete node; | |
node = next; | |
} | |
m_head = nullptr; | |
} | |
} | |
template<typename T> | |
template<typename K> | |
constexpr void LinkedList<T>::insertFirst(const K& value) | |
{ | |
(*this)->insertFirst(static_cast<T>(value)); | |
} | |
template<typename T> | |
template<typename K> | |
constexpr void LinkedList<T>::insertLast(const K& value) | |
{ | |
(*this)->insertLast(static_cast<T>(value)); | |
} | |
template<typename T> | |
void LinkedList<T>::insertFirst(const T& value) | |
{ | |
auto node = new Node<T>(); | |
node->data = value; | |
if (m_head == nullptr) | |
{ | |
m_head = node; | |
m_head->next = nullptr; | |
} | |
else | |
{ | |
auto temp = m_head; | |
m_head = node; | |
m_head->next = temp; | |
} | |
} | |
template<typename T> | |
void LinkedList<T>::insertLast(const T& value) | |
{ | |
auto node = new Node<T>(); | |
node->data = value; | |
node->next = nullptr; | |
if (m_head == nullptr) | |
{ | |
m_head = node; | |
return; | |
} | |
auto temp = m_head; | |
while (temp->next != nullptr) | |
{ | |
temp = temp->next; | |
} | |
node->next = nullptr; | |
temp->next = node; | |
} | |
template<typename T> | |
void LinkedList<T>::removeFirst() | |
{ | |
if (m_head == nullptr) | |
{ | |
return; | |
} | |
m_head = m_head->next; | |
} | |
template<typename T> | |
void LinkedList<T>::removeLast() | |
{ | |
if (m_head == nullptr) | |
{ | |
return; | |
} | |
if (m_head->next == nullptr) | |
{ | |
delete m_head; | |
return; | |
} | |
auto node = m_head; | |
while (node->next->next != nullptr) | |
{ | |
node = node->next; | |
} | |
delete node->next; | |
node->next = nullptr; | |
} | |
template<typename T> | |
size_t LinkedList<T>::size() const | |
{ | |
auto node = m_head; | |
size_t counter = 0; | |
while (node != nullptr) | |
{ | |
counter++; | |
node = node->next; | |
} | |
return counter; | |
} | |
template<typename T> | |
std::string LinkedList<T>::toString() const | |
{ | |
std::stringstream stream; | |
auto node = m_head; | |
if (node != nullptr) | |
{ | |
while (node != nullptr) | |
{ | |
stream << node->data << " -> "; | |
node = node->next; | |
} | |
} | |
stream << "NULL"; | |
return stream.str(); | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "LinkedList.h" | |
#include <ctime> | |
#include <iostream> | |
#include <cstdlib> | |
/** | |
* Demos LinkedList by randomly inserting 10 integers. | |
*/ | |
int main() | |
{ | |
auto list = new LinkedListi(); | |
srand(time(nullptr)); | |
int min = 0; // Min integer | |
int max = 100; // Max integer | |
int n = 10; // Insert 10 random integers. | |
int i = 0; | |
do | |
{ | |
int value = rand() % max + min; | |
std::cout << "Value to insert: " << value << std::endl; | |
list->insertLast(value); | |
std::cout << *list << std::endl; | |
i++; | |
} while (i<n); | |
do | |
{ | |
std::cout << "Removing first value" << std::endl; | |
list->removeFirst(); | |
std::cout << *list << std::endl; | |
} while (list->size() > 0); | |
delete list; list = nullptr; | |
exit(0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment