diff --git a/lab_3/sequences-int/doubly-linked-list.cpp b/lab_3/sequences-int/doubly-linked-list.cpp index 37ab4db..055547d 100644 --- a/lab_3/sequences-int/doubly-linked-list.cpp +++ b/lab_3/sequences-int/doubly-linked-list.cpp @@ -10,36 +10,11 @@ size_t DoublyLinkedList::size() const return count; } -// return pointer to the node at position i, counting from 0 -// for negative numbers, count from the tail (-1) backward (-2, -3, ...) -DoublyLinkedListNode* DoublyLinkedList::index(int i) const -{ - DoublyLinkedListNode* n = this->head; - if(i > 0) - { - for(int k = 0; k < i; k++) - { - assert(n != nullptr); - n = n->get_next(); - } - } - else /** in the doubly linked list, we can walk backward, so let us allow it for negative i **/ - { - DoublyLinkedListNode* n = this->tail; - for(int k = -1; k > i; k--) - { - assert(n != nullptr); - n = n->get_prev(); - } - } - return n; -} - // add an item at the end of the list -void DoublyLinkedList::push_back(const int& pushed_item) +void DoublyLinkedList::enqueue(int value) { DoublyLinkedListNode* new_node = new DoublyLinkedListNode; - new_node->set_item(pushed_item); + new_node->set_item(value); if(this->empty()) this->head = new_node; else @@ -50,115 +25,16 @@ void DoublyLinkedList::push_back(const int& pushed_item) this->tail = new_node; } -// add an item at the beginning of the list -void DoublyLinkedList::push_front(const int& pushed_item) -{ - DoublyLinkedListNode* new_node = new DoublyLinkedListNode; - new_node->set_item(pushed_item); - - if(this->empty()) this->tail = new_node; - else - { - new_node->set_next(this->head); // FIX BUG from the previous version, which was "new_node->set_next(this->head->get_next());" - this->head->set_prev(new_node); // FIX BUG from the previous version, which was "this->head->get_next()->set_prev(new_node);" - } - this->head = new_node; -} - // remove the head node and item -void DoublyLinkedList::pop_front() +int DoublyLinkedList::dequeue() { - if(this->empty()) return; // nothing there to remove + if(this->empty()) return 0; // nothing there to remove DoublyLinkedListNode* successor = this->head->get_next(); - if(successor) successor->set_prev(nullptr); /** we must detach the previous head node from its successor **/ + if(successor) successor->set_prev(nullptr); /** we must detach the previous head node from its successor **/ + int outgoing = this->head->item; delete this->head; this->head = successor; // successor of the previous head is the new head if(this->head == nullptr) this->tail = nullptr; // catch special case: the list is now empty -} - -// remove the tail node and item -/** note how this is much easier for the doubly than for the singly linked list; ** - ** we can simply take the "pop_front()" implementation and do everything symmetrically **/ -void DoublyLinkedList::pop_back() -{ - if(this->empty()) return; // nothing there to remove - DoublyLinkedListNode* predecessor = this->tail->get_prev(); - - if(predecessor) predecessor->set_next(nullptr); - delete this->tail; - this->tail = predecessor; /** predecessor of the previous tail is the new tail **/ - if(this->tail == nullptr) this->head = nullptr; /** catch special case: the list is now empty **/ -} - -// insert an item at index i -// for negative numbers, count from the tail (-1) backward (-2, -3, ...) -void DoublyLinkedList::insert_at(int i, const int& inserted_item) -{ - if(i == 0) - { - this->push_front(inserted_item); - return; - } - else if(i == -1) - { - this->push_back(inserted_item); - return; - } - DoublyLinkedListNode* predecessor = this->index(i-1); - this->insert_successor_to(predecessor, inserted_item); -} - -// remove the item at index i -// for negative numbers, count from the tail (-1) backward (-2, -3, ...) -void DoublyLinkedList::erase_at(int i) -{ - if(i == 0) - { - this->pop_front(); - return; - } - else if(i == -1) - { - this->pop_back(); - return; - } - DoublyLinkedListNode* erased_node = this->index(i); - this->erase_node(erased_node); -} - -// insert an item after given node -void DoublyLinkedList::insert_successor_to(DoublyLinkedListNode* predecessor, const int& inserted_item) -{ - DoublyLinkedListNode* new_node = new DoublyLinkedListNode; - new_node->set_item(inserted_item); - - DoublyLinkedListNode* successor = predecessor->get_next(); - predecessor->set_next(new_node); - new_node->set_prev(predecessor); /** attach both ways **/ - new_node->set_next(successor); - - if(!successor) this->tail = new_node; - else successor->set_prev(new_node); /** attach both ways **/ -} - -/** remove "erased_node" from the doubly linked list **/ -void DoublyLinkedList::erase_node(DoublyLinkedListNode* erased_node) -{ - if(erased_node->get_prev() == nullptr) /** erase the head **/ - { - this->pop_front(); - return; - } - if(erased_node->get_next() == nullptr) /** erase the tail **/ - { - this->pop_back(); - return; - } - - /** now attach predecessor and successor to each other **/ - erased_node->get_prev()->set_next(erased_node->get_next()); - erased_node->get_next()->set_prev(erased_node->get_prev()); - - delete erased_node; /** "erased_node" detached now, we can delete it **/ -} + return outgoing; +} \ No newline at end of file diff --git a/lab_3/sequences-int/doubly-linked-list.h b/lab_3/sequences-int/doubly-linked-list.h index 4b97177..f3126f7 100644 --- a/lab_3/sequences-int/doubly-linked-list.h +++ b/lab_3/sequences-int/doubly-linked-list.h @@ -2,6 +2,7 @@ #define DOUBLY_LINKED_LIST_H #include +#include "queue.h" #include "sequence.h" namespace seq @@ -37,61 +38,20 @@ namespace seq friend class DoublyLinkedList; // allow DoublyLinkedList to access private members }; - class DoublyLinkedList: public Sequence + class DoublyLinkedList: public Queue { public: bool empty() const { return (this->head == nullptr); } // test whether the doubly linked list is empty size_t size() const; // return the size (number of items in the doubly linked list) - // it is the caller's responsibility to ensure that the list is not empty when calling front() or back()! - int& front() { assert(this->head); return this->head->get_item(); } // return a reference to the first item - int& back() { assert(this->tail); return this->tail->get_item(); } // return a reference to the final item + void enqueue(int element); + int dequeue(); - // return a reference to the item at position i of the list, counting from 0 - // for negative numbers, count from the tail (-1) backward (-2, -3, ...) - // it is the caller's responsibility that the index is within range - int& at(int i) { return this->index(i)->get_item(); } - // return pointer to the head/tail node DoublyLinkedListNode* begin() const { return this->head; } DoublyLinkedListNode* end() const { return this->tail; } - - // return pointer to the node at position i, counting from 0 - // for negative numbers, count from the tail (-1) backward (-2, -3, ...) - DoublyLinkedListNode* index(int i) const; - /* - * accepts an additional item into the doubly linked list; - * by default, this is done at the back end of the list - * call push_front(...) to push an element at the front - * - * the list takes ownership of the copy (but not of the original!) - */ - void push(const int& pushed_item) { this->push_back(pushed_item); } - void push_back(const int& pushed_item); - void push_front(const int& pushed_item); - - /* - * removes an item from the list (front end by default) - * to do the same at the back, call pop_back() - */ - void pop() { this->pop_front(); } - void pop_front(); - void pop_back(); - void clear() { while(!this->empty()) this->pop(); } // remove all the items from the list - - // it is the caller's responsibility that the index is within range - // for negative numbers, count from the tail (-1) backward (-2, -3, ...) - void insert_at(int i, const int& inserted_item); // insert an item at index i - void erase_at(int i); // remove the item at index i - - // it is the caller's responsibility that the node is actually part of the list - void insert_successor_to(DoublyLinkedListNode* predecessor, const int& inserted_item); // insert an item after given node - void erase_successor_to(DoublyLinkedListNode* predecessor) // remove the item after given node - { - this->erase_node(predecessor->get_next()); - } - void erase_node(DoublyLinkedListNode* erased_node); + void clear() { while(!this->empty()) this->dequeue(); } // remove all the items from the list ~DoublyLinkedList() { this->clear(); } diff --git a/lab_3/sequences-int/sequence-test.cpp b/lab_3/sequences-int/sequence-test.cpp index ffc809d..c90c69b 100644 --- a/lab_3/sequences-int/sequence-test.cpp +++ b/lab_3/sequences-int/sequence-test.cpp @@ -56,12 +56,12 @@ int main() std::cout << "\n\n*** test with singly linked list ***\n"; seq::SinglyLinkedList sll; float sll_time = test_with_time_measurement(&sll, iterations); - /* + std::cout << "\n\n*** test with doubly linked list ***\n"; seq::DoublyLinkedList dll; float dll_time = test_with_time_measurement(&dll, iterations); - */ + //std::cout << "\n\nRuntime for dynamic array:\t" << dyna_time << " s\n"; std::cout << "Runtime for singly linked list:\t" << sll_time << " s\n"; - //std::cout << "Runtime for doubly linked list:\t" << dll_time << " s\n"; + std::cout << "Runtime for doubly linked list:\t" << dll_time << " s\n"; } diff --git a/lab_3/sequences-int/singly-linked-list.cpp b/lab_3/sequences-int/singly-linked-list.cpp index fd3c3f8..b44f4e6 100644 --- a/lab_3/sequences-int/singly-linked-list.cpp +++ b/lab_3/sequences-int/singly-linked-list.cpp @@ -25,9 +25,9 @@ int SinglyLinkedList::dequeue() { if(this->empty()) return 0; // nothing there to remove SinglyLinkedListNode* successor = this->head->get_next(); - int result = this->head->item; + int outgoing = this->head->item; delete this->head; this->head = successor; // successor of the previous head is the new head if(this->head == nullptr) this->tail = nullptr; // catch special case: the list is now empty - return result; + return outgoing; } \ No newline at end of file