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

Here

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;
}