diff --git a/AK/HashTable.h b/AK/HashTable.h index 0b211a6e1b..dca176a759 100644 --- a/AK/HashTable.h +++ b/AK/HashTable.h @@ -1,10 +1,10 @@ #pragma once -#include "Assertions.h" -#include "DoublyLinkedList.h" -#include "StdLibExtras.h" -#include "Traits.h" -#include "kstdio.h" +#include +#include +#include +#include +#include namespace AK { @@ -75,7 +75,7 @@ private: template class HashTable { private: - using Bucket = DoublyLinkedList; + using Bucket = SinglyLinkedList; public: HashTable() {} @@ -136,12 +136,12 @@ public: void dump() const; - using Iterator = HashTableIterator::Iterator>; + using Iterator = HashTableIterator::Iterator>; friend Iterator; Iterator begin() { return Iterator(*this, is_empty()); } Iterator end() { return Iterator(*this, true); } - using ConstIterator = HashTableIterator::ConstIterator>; + using ConstIterator = HashTableIterator::ConstIterator>; friend ConstIterator; ConstIterator begin() const { return ConstIterator(*this, is_empty()); } ConstIterator end() const { return ConstIterator(*this, true); } diff --git a/AK/SinglyLinkedList.h b/AK/SinglyLinkedList.h index 34e837c465..d6d55b5917 100644 --- a/AK/SinglyLinkedList.h +++ b/AK/SinglyLinkedList.h @@ -4,6 +4,32 @@ namespace AK { +template +class SinglyLinkedListIterator { +public: + bool operator!=(const SinglyLinkedListIterator& other) const { return m_node != other.m_node; } + SinglyLinkedListIterator& operator++() + { + m_prev = m_node; + m_node = m_node->next; + return *this; + } + ElementType& operator*() { return m_node->value; } + ElementType* operator->() { return &m_node->value; } + bool is_end() const { return !m_node; } + static SinglyLinkedListIterator universal_end() { return SinglyLinkedListIterator(nullptr); } + +private: + friend ListType; + explicit SinglyLinkedListIterator(typename ListType::Node* node, typename ListType::Node* prev = nullptr) + : m_node(node) + , m_prev(prev) + { + } + typename ListType::Node* m_node { nullptr }; + typename ListType::Node* m_prev { nullptr }; +}; + template class SinglyLinkedList { private: @@ -12,6 +38,10 @@ private: : value(move(v)) { } + explicit Node(const T& v) + : value(v) + { + } T value; Node* next { nullptr }; }; @@ -74,6 +104,18 @@ public: return value; } + void append(const T& value) + { + auto* node = new Node(value); + if (!m_head) { + m_head = node; + m_tail = node; + return; + } + m_tail->next = node; + m_tail = node; + } + void append(T&& value) { auto* node = new Node(move(value)); @@ -95,75 +137,51 @@ public: return false; } - class Iterator { - public: - bool operator!=(const Iterator& other) { return m_node != other.m_node; } - Iterator& operator++() - { - m_node = m_node->next; - return *this; - } - T& operator*() { return m_node->value; } - bool is_end() const { return !m_node; } - static Iterator universal_end() { return Iterator(nullptr); } - - private: - friend class SinglyLinkedList; - explicit Iterator(SinglyLinkedList::Node* node) - : m_node(node) - { - } - SinglyLinkedList::Node* m_node; - }; - + using Iterator = SinglyLinkedListIterator; + friend Iterator; Iterator begin() { return Iterator(m_head); } Iterator end() { return Iterator::universal_end(); } - class ConstIterator { - public: - bool operator!=(const ConstIterator& other) { return m_node != other.m_node; } - ConstIterator& operator++() - { - m_node = m_node->next; - return *this; - } - const T& operator*() const { return m_node->value; } - bool is_end() const { return !m_node; } - static ConstIterator universal_end() { return ConstIterator(nullptr); } - - private: - friend class SinglyLinkedList; - explicit ConstIterator(const SinglyLinkedList::Node* node) - : m_node(node) - { - } - const SinglyLinkedList::Node* m_node; - }; - + using ConstIterator = SinglyLinkedListIterator; + friend ConstIterator; ConstIterator begin() const { return ConstIterator(m_head); } ConstIterator end() const { return ConstIterator::universal_end(); } ConstIterator find(const T& value) const { + Node* prev = nullptr; for (auto* node = m_head; node; node = node->next) { if (node->value == value) - return ConstIterator(node); + return ConstIterator(node, prev); + prev = node; } return end(); } Iterator find(const T& value) { + Node* prev = nullptr; for (auto* node = m_head; node; node = node->next) { if (node->value == value) - return Iterator(node); + return Iterator(node, prev); + prev = node; } return end(); } -private: - friend class Iterator; + void remove(Iterator iterator) + { + ASSERT(!iterator.is_end()); + if (m_head == iterator.m_node) + m_head = iterator.m_node->next; + if (m_tail == iterator.m_node) + m_tail = iterator.m_prev; + if (iterator.m_prev) + iterator.m_prev->next = iterator.m_node->next; + delete iterator.m_node; + } +private: Node* head() { return m_head; } const Node* head() const { return m_head; } diff --git a/AK/Tests/TestHashMap.cpp b/AK/Tests/TestHashMap.cpp index f3ec4cd9de..0820cd9c42 100644 --- a/AK/Tests/TestHashMap.cpp +++ b/AK/Tests/TestHashMap.cpp @@ -23,6 +23,14 @@ int main() ++loop_counter; } + number_to_string.remove(1); + EXPECT_EQ(number_to_string.size(), 2); + EXPECT(number_to_string.find(1) == number_to_string.end()); + + number_to_string.remove(3); + EXPECT_EQ(number_to_string.size(), 1); + EXPECT(number_to_string.find(3) == number_to_string.end()); + EXPECT_EQ(loop_counter, 3); return 0; }