- Published on
The Algorithm Design Manual (3rd) Exercise Solution 'E3-3'
Table of Contents
Introduction
This series is my solutions for algorithm exercises in'The Algorithm Design Manual' 3rd edition.
It's my solutions, not model answers, so if you find some mistakes or more sophisticated solutions, please post in comment area below.
Repository
Exercise 3-3
Question
Give an algorithm to reverse the direction of a given singly linked list. In other words, after the reversal all pointers should now point backwards. Your algorithm should take linear time.
Solution
C++ code.
#include <cassert>
#include <string>
#include <utility>
// implement simply linked list class
template <typename T>
class Singly_linked_list {
private:
struct node {
T item;
node* next;
};
node* head;
public:
Singly_linked_list() = delete;
Singly_linked_list(const Singly_linked_list&) = delete;
Singly_linked_list(Singly_linked_list&&) = delete;
Singly_linked_list(std::initializer_list<T> list) {
if (!list.size()) return;
auto p_l{std::cbegin(list)};
node* prev;
head = new node;
head->item = *p_l++;
prev = head;
for (; p_l != std::cend(list); p_l++) {
node* p_node = new node;
p_node->item = *p_l;
prev->next = p_node;
prev = p_node;
}
}
~Singly_linked_list() noexcept {
if (!head) return;
for (node* next{head}; next;) {
node* p_node;
p_node = next;
next = p_node->next;
delete p_node;
}
};
Singly_linked_list& operator=(const Singly_linked_list&) = delete;
Singly_linked_list& operator=(Singly_linked_list&&) = delete;
// Implement reverse logic
// Reconnect its next pointer to the prev node
// Recursively repeat reconnection
void reverse() {
if (!head) return;
node* next{head->next};
node* prev{head};
head->next = nullptr;
while (next) {
node* p_node = next;
next = p_node->next;
p_node->next = prev;
prev = p_node;
}
head = prev;
}
// Iterator implementation for data to be exposed and asserted
struct Iterator {
Iterator() : current_node{nullptr} {};
Iterator(node* node) : current_node{node} {};
Iterator& operator++() {
if (current_node) {
current_node = current_node->next;
}
return *this;
}
Iterator operator++(int) {
Iterator it_temp{*this};
++(*this);
return it_temp;
}
bool operator==(const Iterator& it) const {
return this->current_node == it.current_node;
}
bool operator!=(const Iterator& it) const { return !(this == it); }
T operator*() const { return this->current_node->item; }
private:
node* current_node;
};
Iterator begin() const { return Iterator(head); }
Iterator end() const { return Iterator(); }
};
int main(int argc, char const* argv[]) {
{
Singly_linked_list<int> ll{1, 2, 3, 4, 5};
ll.reverse();
auto it(ll.begin());
assert(*it++ == 5);
assert(*it++ == 4);
assert(*it++ == 3);
assert(*it++ == 2);
assert(*it++ == 1);
assert(it == ll.end());
ll.reverse();
it = ll.begin();
assert(*it++ == 1);
assert(*it++ == 2);
assert(*it++ == 3);
assert(*it++ == 4);
assert(*it++ == 5);
assert(it == ll.end());
}
{
Singly_linked_list<int> ll{10};
ll.reverse();
auto it{ll.begin()};
assert(*it++ == 10);
assert(it == ll.end());
}
{
Singly_linked_list<std::string> ll{"apple", "lemon", "grape"};
ll.reverse();
auto it{ll.begin()};
assert(*it++ == "grape");
assert(*it++ == "lemon");
assert(*it++ == "apple");
assert(it == ll.end());
}
return 0;
}