-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
191 additions
and
11 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,10 @@ | ||
VPATH = src | ||
DIST = dist | ||
CPPFLAGS = | ||
CXXFLAGS = -Wall -Wextra -Werror -Wpedantic -std=c++23 | ||
CXX = g++ | ||
|
||
all: $(DIST)/test dist | ||
all: tests | ||
|
||
dist: | ||
mkdir dist | ||
tests: | ||
cd test && $(MAKE) | ||
|
||
$(DIST)/test: linked-list/test.cpp | ||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -o $@ $^ | ||
|
||
PHONY clean: | ||
clean: | ||
-rm dist/* | ||
cd test && $(MAKE) clean |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
#ifndef LINKED_LIST_HPP | ||
#define LINKED_LIST_HPP | ||
|
||
#include <algorithm> | ||
#include <utility> | ||
|
||
template <typename T> class LinkedList { | ||
private: | ||
struct Node { | ||
Node *next = nullptr; | ||
T value; | ||
|
||
Node(T v) : value(std::move(v)){}; | ||
|
||
~Node() = default; | ||
}; | ||
|
||
Node *head = nullptr; | ||
|
||
class Iterator { | ||
public: | ||
using iterator_category = std::forward_iterator_tag; | ||
using difference_type = std::ptrdiff_t; | ||
using element_type = T; | ||
using value_type = T; | ||
using pointer = Node *; | ||
using reference = T &; | ||
|
||
private: | ||
Node *node = nullptr; | ||
Node *sentinel = nullptr; | ||
static_assert(std::sentinel_for<decltype(sentinel), decltype(node)>); | ||
|
||
public: | ||
Iterator() {} | ||
|
||
Iterator(pointer n) : node(n) {} | ||
|
||
reference operator*() const { return node->value; } | ||
|
||
pointer operator->() const { return node; } | ||
|
||
Iterator &operator++() { | ||
if (node != sentinel) { | ||
node = node->next; | ||
} | ||
|
||
return *this; | ||
} | ||
|
||
Iterator operator++(int) { | ||
auto old = *this; | ||
++(*this); | ||
return old; | ||
} | ||
|
||
friend bool operator==(const Iterator &a, const Iterator &b) { | ||
return a.node == b.node; | ||
}; | ||
}; | ||
|
||
static_assert(std::forward_iterator<Iterator>); | ||
|
||
public: | ||
LinkedList() = default; | ||
|
||
~LinkedList() { clear(); } | ||
|
||
void clear() { | ||
Node *current = head; | ||
|
||
while (current) { | ||
Node *previous = current; | ||
current = current->next; | ||
delete previous; | ||
} | ||
|
||
head = nullptr; | ||
} | ||
|
||
Iterator begin() const { return Iterator{head}; } | ||
|
||
Iterator end() const { return Iterator{nullptr}; } | ||
|
||
bool empty() { return head == nullptr; } | ||
|
||
T &front() { return head->value; } | ||
|
||
void push_front(T value) { | ||
Node *node = new Node(std::move(value)); | ||
|
||
if (empty()) { | ||
head = node; | ||
} else { | ||
node->next = head; | ||
head = node; | ||
} | ||
} | ||
|
||
template <class... Args> T &emplace_front(Args &&...args) { | ||
T value(std::forward<Args>(args)...); | ||
|
||
push_front(std::move(value)); | ||
|
||
return front(); | ||
} | ||
|
||
void pop_front() noexcept { | ||
if (!empty()) { | ||
Node *next = head->next; | ||
delete head; | ||
head = next; | ||
} | ||
} | ||
}; | ||
|
||
#endif |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
#include <algorithm> | ||
#include <catch2/catch_test_macros.hpp> | ||
#include <iostream> | ||
#include <string> | ||
#include <vector> | ||
|
||
#include "../src/linked_list.hpp" | ||
|
||
TEST_CASE("Initialize a new list") { | ||
LinkedList<int> list; | ||
|
||
REQUIRE(list.empty()); | ||
} | ||
|
||
TEST_CASE("Add element to list") { | ||
LinkedList<int> list; | ||
list.push_front(123); | ||
|
||
REQUIRE(list.front() == 123); | ||
} | ||
|
||
TEST_CASE("Move element to list") { | ||
LinkedList<std::string> list; | ||
std::string string{"Hello, Twitch!"}; | ||
list.push_front(std::move(string)); | ||
|
||
REQUIRE(list.front() == "Hello, Twitch!"); | ||
REQUIRE(string == ""); | ||
} | ||
|
||
TEST_CASE("Clear list") { | ||
LinkedList<int> list; | ||
list.push_front(123); | ||
list.push_front(234); | ||
list.push_front(345); | ||
list.clear(); | ||
|
||
REQUIRE(list.empty()); | ||
} | ||
|
||
TEST_CASE("Create value and push to list") { | ||
LinkedList<std::string> list; | ||
std::string string = list.emplace_front("Hello, Twitch!"); | ||
|
||
REQUIRE(string == "Hello, Twitch!"); | ||
REQUIRE(list.front() == "Hello, Twitch!"); | ||
} | ||
|
||
TEST_CASE("Pop a single element") { | ||
LinkedList<int> list; | ||
list.push_front(123); | ||
|
||
REQUIRE(!list.empty()); | ||
|
||
list.pop_front(); | ||
|
||
REQUIRE(list.empty()); | ||
} | ||
|
||
TEST_CASE("Print content") { | ||
LinkedList<int> list; | ||
list.push_front(123); | ||
list.push_front(234); | ||
list.push_front(345); | ||
|
||
std::vector<int> vector; | ||
vector.assign(list.begin(), list.end()); | ||
|
||
REQUIRE(vector == std::vector{345, 234, 123}); | ||
} |