Program Listing for File singly_linked_list.h
↰ Return to documentation for file (data_structures/singly_linked_list.h)
#ifndef DATA_STRUCTURES_SINGLY_LINKED_LIST_H
#define DATA_STRUCTURES_SINGLY_LINKED_LIST_H
#include <iostream>
#include <stdexcept>
namespace DataStructures {
template <typename T>
class SinglyLinkedList {
public:
SinglyLinkedList()
{
head = new Node(T());
tail = head;
size = 0;
}
~SinglyLinkedList()
{
Node* cur = head;
while (cur != nullptr) {
Node* next = cur->next;
delete cur;
cur = next;
}
}
/* Add functions */
void add_first(const T& data)
{
Node* x = new Node(data);
x->next = head->next;
head->next = x;
if (size == 0) {
tail = x;
}
size++;
}
void add_last(const T& data)
{
Node* x = new Node(data);
tail->next = x;
tail = x;
size++;
}
void add(int pos_index, const T& data)
{
check_position_index(pos_index);
if (pos_index == int(size)) {
add_last(data);
return;
}
Node* prev = head;
for (int i = 0; i < pos_index; i++) {
prev = prev->next;
}
Node* x = new Node(data);
x->next = prev->next;
prev->next = x;
size++;
}
/* Erase functions */
T del_first()
{
if (is_empty()) {
throw std::out_of_range("No nodes to remove");
}
Node* first = head->next;
head->next = first->next;
if (size == 1) {
tail = head;
}
size--;
T data = first->data;
delete first;
return data;
}
T del_last()
{
if (is_empty()) {
throw std::out_of_range("No nodes to remove");
}
Node* prev = head;
while (prev->next != tail) {
prev = prev->next;
}
T data = tail->data;
delete tail;
prev->next = nullptr;
tail = prev;
size--;
return data;
}
T del(int index)
{
check_element_index(index);
Node* prev = head;
for (int i = 0; i < index; i++) {
prev = prev->next;
}
Node* x = prev->next;
prev->next = x->next;
if (index == int(size) - 1) {
tail = prev;
}
size--;
T data = x->data;
delete x;
return data;
}
/* Get functions */
T get_first() const
{
if (is_empty()) {
throw std::out_of_range("No nodes in the list");
}
return head->next->data;
}
T get_last() const
{
if (is_empty()) {
throw std::out_of_range("No nodes in the list");
}
return tail->data;
}
T get(int index) const
{
Node* p = get_node(index);
return p->data;
}
/* Set function */
T set(int index, const T& data)
{
Node* p = get_node(index);
T x = p->data;
p->data = data;
return x;
}
/* Utility functions */
size_t get_size() const { return size; }
bool is_empty() const { return size == 0; }
void display() const
{
std::cout << "Size = " << size << '\n';
Node* p = head->next;
while (p != tail) {
std::cout << p->data << "->";
p = p->next;
}
std::cout << "nullptr" << '\n';
std::cout << '\n';
}
private:
struct Node {
T data;
Node* next;
Node(T val) : data(val), next(nullptr) {}
};
Node* head;
Node* tail;
size_t size;
Node* get_node(int index) const
{
check_element_index(index);
Node* p = head->next;
for (int i = 0; i < index; i++) {
p = p->next;
}
return p;
}
bool is_element_index(int index) const
{
return index >= 0 && index < int(size);
}
bool is_position_index(int pos_index) const
{
return pos_index >= 0 && pos_index <= int(size);
}
void check_element_index(int index) const
{
if (!is_element_index(index)) {
throw std::out_of_range(
"Index: " + std::to_string(index) +
", Size: " + std::to_string(size));
}
}
void check_position_index(int pos_index) const
{
if (!is_position_index(pos_index)) {
throw std::out_of_range(
"Index: " + std::to_string(pos_index) +
", Size: " + std::to_string(size));
}
}
};
} // namespace DataStructures
#endif // DATA_STRUCTURES_LINKED_LIST_H