17
This commit is contained in:
parent
2314cf70aa
commit
5a3aa29482
12
lab_3/sequences-int/queue.h
Normal file
12
lab_3/sequences-int/queue.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#ifndef QUEUE_H
|
||||||
|
#define QUEUE_H
|
||||||
|
|
||||||
|
namespace seq {
|
||||||
|
class Queue {
|
||||||
|
public:
|
||||||
|
virtual void enqueue(int element) = 0;
|
||||||
|
virtual int dequeue() = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -3,6 +3,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "dynamic-array.h"
|
#include "dynamic-array.h"
|
||||||
|
#include "queue.h"
|
||||||
#include "singly-linked-list.h"
|
#include "singly-linked-list.h"
|
||||||
#include "doubly-linked-list.h"
|
#include "doubly-linked-list.h"
|
||||||
|
|
||||||
@ -11,52 +12,17 @@ namespace
|
|||||||
/*
|
/*
|
||||||
* run a simple test
|
* run a simple test
|
||||||
*/
|
*/
|
||||||
void test_sequence(seq::Sequence* sqn, int n, int m, std::ostream* os)
|
void test_sequence(seq::Queue* sqn, int n, int m, std::ostream* os)
|
||||||
{
|
{
|
||||||
assert((m > 0) && (n > m));
|
assert((m > 0) && (n > m));
|
||||||
if(os) *os << "Push even numbers from 0 to " << 2*(n-1) << ".\n";
|
if(os) *os << "Enqueue even numbers from 0 to " << 2*(n-1) << ".\n";
|
||||||
for(int i = 0; i < n; i++) sqn->push(2*i);
|
for(int i = 0; i < n; i++) sqn->enqueue(2*i);
|
||||||
|
|
||||||
if(os) *os << "Overwrite element at index " << m/2 << " with 0.\n";
|
|
||||||
int& item = sqn->at(m/2);
|
|
||||||
item = 0;
|
|
||||||
|
|
||||||
if(os) *os << "\nSize of sequence: " << sqn->size() << ".\n";
|
|
||||||
if(os) *os << "Detaching " << m/2 << " elements from front:";
|
|
||||||
for(int i = 0; i < m/2; i++)
|
|
||||||
{
|
|
||||||
if(os) *os << " " << sqn->front();
|
|
||||||
sqn->pop_front();
|
|
||||||
}
|
|
||||||
if(os) *os << ".\nDetaching " << m/2 << " elements from back:";
|
|
||||||
for(int i = 0; i < m/2; i++)
|
|
||||||
{
|
|
||||||
if(os) *os << " " << sqn->back();
|
|
||||||
sqn->pop_back();
|
|
||||||
}
|
|
||||||
if(os) *os << ".\nSize of sequence: " << sqn->size() << ".\n";
|
|
||||||
|
|
||||||
if(os) *os << "\nElement at index " << (n-m)/3 << ": " << sqn->at((n-m)/3) << ".\n";
|
|
||||||
if(os) *os << "Element at index " << 2*(n-m)/3 << ": " << sqn->at(2*(n-m)/3) << ".\n";
|
|
||||||
|
|
||||||
if(os) *os << "\nInsert " << m << " at index " << 2*(n-m)/3 << ".\n";
|
|
||||||
sqn->insert_at(2*(n-m)/3, m);
|
|
||||||
if(os) *os << "Size of sequence: " << sqn->size() << ".\n";
|
|
||||||
|
|
||||||
if(os) *os << "\nDelete element at index " << (n-m)/3 << ".\n";
|
|
||||||
sqn->erase_at((n-m)/3);
|
|
||||||
if(os) *os << "Size of sequence: " << sqn->size() << ".\n";
|
|
||||||
if(os) *os << "Element at index " << 2*(n-m)/3 - 1 << ": " << sqn->at(2*(n-m)/3 - 1) << ".\n";
|
|
||||||
|
|
||||||
if(os) *os << "\nClearing.\n";
|
|
||||||
sqn->clear();
|
|
||||||
if(os) *os << "Size of sequence: " << sqn->size() << ".\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* return time measurement in units of seconds
|
* return time measurement in units of seconds
|
||||||
*/
|
*/
|
||||||
float test_with_time_measurement(seq::Sequence* sqn, int iterations)
|
float test_with_time_measurement(seq::Queue* sqn, int iterations)
|
||||||
{
|
{
|
||||||
int sequence_length = 200001;
|
int sequence_length = 200001;
|
||||||
int deletions = 10;
|
int deletions = 10;
|
||||||
@ -82,20 +48,20 @@ namespace
|
|||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
int iterations = 200;
|
int iterations = 200;
|
||||||
|
/*
|
||||||
std::cout << "*** test with dynamic array ***\n";
|
std::cout << "*** test with dynamic array ***\n";
|
||||||
seq::DynamicArray dyna;
|
seq::DynamicArray dyna;
|
||||||
float dyna_time = test_with_time_measurement(&dyna, iterations);
|
float dyna_time = test_with_time_measurement(&dyna, iterations);
|
||||||
|
*/
|
||||||
std::cout << "\n\n*** test with singly linked list ***\n";
|
std::cout << "\n\n*** test with singly linked list ***\n";
|
||||||
seq::SinglyLinkedList sll;
|
seq::SinglyLinkedList sll;
|
||||||
float sll_time = test_with_time_measurement(&sll, iterations);
|
float sll_time = test_with_time_measurement(&sll, iterations);
|
||||||
|
/*
|
||||||
std::cout << "\n\n*** test with doubly linked list ***\n";
|
std::cout << "\n\n*** test with doubly linked list ***\n";
|
||||||
seq::DoublyLinkedList dll;
|
seq::DoublyLinkedList dll;
|
||||||
float dll_time = test_with_time_measurement(&dll, iterations);
|
float dll_time = test_with_time_measurement(&dll, iterations);
|
||||||
|
*/
|
||||||
std::cout << "\n\nRuntime for dynamic array:\t" << dyna_time << " s\n";
|
//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 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";
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "singly-linked-list.h"
|
#include "singly-linked-list.h"
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
using namespace seq;
|
using namespace seq;
|
||||||
|
|
||||||
@ -10,131 +11,23 @@ size_t SinglyLinkedList::size() const
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
// return pointer to the node at position i, counting from 0
|
void SinglyLinkedList::enqueue(int value)
|
||||||
SinglyLinkedListNode* SinglyLinkedList::index(int i) const
|
|
||||||
{
|
|
||||||
SinglyLinkedListNode* n = this->head;
|
|
||||||
for(int k = 0; k < i; k++)
|
|
||||||
{
|
|
||||||
assert(n != nullptr);
|
|
||||||
n = n->get_next();
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add an item at the end of the list
|
|
||||||
void SinglyLinkedList::push_back(const int& pushed_item)
|
|
||||||
{
|
{
|
||||||
SinglyLinkedListNode* new_node = new SinglyLinkedListNode;
|
SinglyLinkedListNode* new_node = new SinglyLinkedListNode;
|
||||||
new_node->set_item(pushed_item);
|
new_node->set_item(value);
|
||||||
|
|
||||||
if(this->empty()) this->head = new_node;
|
if(this->empty()) this->head = new_node;
|
||||||
else this->tail->set_next(new_node);
|
else this->tail->set_next(new_node);
|
||||||
this->tail = new_node;
|
this->tail = new_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add an item at the beginning of the list
|
int SinglyLinkedList::dequeue()
|
||||||
void SinglyLinkedList::push_front(const int& pushed_item)
|
|
||||||
{
|
{
|
||||||
SinglyLinkedListNode* new_node = new SinglyLinkedListNode;
|
if(this->empty()) return 0; // nothing there to remove
|
||||||
new_node->set_item(pushed_item);
|
|
||||||
|
|
||||||
if(this->empty()) this->tail = new_node;
|
|
||||||
else new_node->set_next(this->head); // FIG BUG from previous version, which was "else new_node->set_next(this->head->get_next());"
|
|
||||||
this->head = new_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove the head node and item
|
|
||||||
void SinglyLinkedList::pop_front()
|
|
||||||
{
|
|
||||||
if(this->empty()) return; // nothing there to remove
|
|
||||||
SinglyLinkedListNode* successor = this->head->get_next();
|
SinglyLinkedListNode* successor = this->head->get_next();
|
||||||
|
int result = this->head->item;
|
||||||
delete this->head;
|
delete this->head;
|
||||||
this->head = successor; // successor of the previous head is the new 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
|
if(this->head == nullptr) this->tail = nullptr; // catch special case: the list is now empty
|
||||||
}
|
return result;
|
||||||
|
|
||||||
// remove the tail node and item
|
|
||||||
// note: in a singly linked list, we need to walk step by step to the end!
|
|
||||||
void SinglyLinkedList::pop_back()
|
|
||||||
{
|
|
||||||
if(this->empty()) return; // nothing there to remove
|
|
||||||
|
|
||||||
// list only contains one element
|
|
||||||
if(this->head->get_next() == nullptr)
|
|
||||||
{
|
|
||||||
delete this->head;
|
|
||||||
this->head = nullptr;
|
|
||||||
this->tail = nullptr;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* walk through until "third" is nullptr, second is the last element, and first is the second-to-last
|
|
||||||
*/
|
|
||||||
SinglyLinkedListNode* first = this->head;
|
|
||||||
SinglyLinkedListNode* second = first->get_next();
|
|
||||||
SinglyLinkedListNode* third = second->get_next();
|
|
||||||
while(third != nullptr)
|
|
||||||
{
|
|
||||||
first = second;
|
|
||||||
second = third;
|
|
||||||
third = third->get_next();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* remove "second"
|
|
||||||
*/
|
|
||||||
if(this->tail == second) this->tail = first;
|
|
||||||
first->set_next(nullptr);
|
|
||||||
delete second;
|
|
||||||
}
|
|
||||||
|
|
||||||
// insert an item at index i
|
|
||||||
void SinglyLinkedList::insert_at(int i, const int& inserted_item)
|
|
||||||
{
|
|
||||||
if(i == 0)
|
|
||||||
{
|
|
||||||
this->push_front(inserted_item);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SinglyLinkedListNode* predecessor = this->index(i-1);
|
|
||||||
this->insert_successor_to(predecessor, inserted_item);
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove the item at index i
|
|
||||||
void SinglyLinkedList::erase_at(int i)
|
|
||||||
{
|
|
||||||
if(i == 0)
|
|
||||||
{
|
|
||||||
this->pop_front();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SinglyLinkedListNode* predecessor = this->index(i-1);
|
|
||||||
this->erase_successor_to(predecessor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// insert an item after given node
|
|
||||||
void SinglyLinkedList::insert_successor_to(SinglyLinkedListNode* predecessor, const int& inserted_item)
|
|
||||||
{
|
|
||||||
SinglyLinkedListNode* new_node = new SinglyLinkedListNode;
|
|
||||||
new_node->set_item(inserted_item);
|
|
||||||
|
|
||||||
SinglyLinkedListNode* successor = predecessor->get_next();
|
|
||||||
predecessor->set_next(new_node);
|
|
||||||
new_node->set_next(successor);
|
|
||||||
|
|
||||||
if(!successor) this->tail = new_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove the item after given node
|
|
||||||
void SinglyLinkedList::erase_successor_to(SinglyLinkedListNode* predecessor)
|
|
||||||
{
|
|
||||||
SinglyLinkedListNode* erased_node = predecessor->get_next();
|
|
||||||
SinglyLinkedListNode* new_successor = erased_node->get_next();
|
|
||||||
|
|
||||||
predecessor->set_next(new_successor);
|
|
||||||
if(new_successor == nullptr) this->tail = predecessor;
|
|
||||||
delete erased_node;
|
|
||||||
}
|
}
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "sequence.h"
|
#include "sequence.h"
|
||||||
|
#include "queue.h"
|
||||||
|
|
||||||
namespace seq
|
namespace seq
|
||||||
{
|
{
|
||||||
@ -29,55 +30,16 @@ namespace seq
|
|||||||
friend class SinglyLinkedList; // allow SinglyLinkedList to access private members
|
friend class SinglyLinkedList; // allow SinglyLinkedList to access private members
|
||||||
};
|
};
|
||||||
|
|
||||||
class SinglyLinkedList: public Sequence
|
class SinglyLinkedList: public Queue
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool empty() const { return (this->head == nullptr); } // test whether the singly linked list is empty
|
bool empty() const { return (this->head == nullptr); } // test whether the singly linked list is empty
|
||||||
size_t size() const; // return the size (number of items in the singly linked list)
|
size_t size() const; // return the size (number of items in the singly linked list)
|
||||||
|
|
||||||
// it is the caller's responsibility to ensure that the list is not empty when calling front() or back()!
|
void enqueue(int element);
|
||||||
int& front() { assert(this->head); return this->head->get_item(); } // return a reference to the first item
|
int dequeue();
|
||||||
int& back() { assert(this->tail); return this->tail->get_item(); } // return a reference to the final item
|
|
||||||
|
|
||||||
// return a reference to the item at position i of the list, counting from 0
|
|
||||||
// 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
|
|
||||||
SinglyLinkedListNode* begin() const { return this->head; }
|
|
||||||
SinglyLinkedListNode* end() const { return this->tail; }
|
|
||||||
|
|
||||||
// return pointer to the node at position i, counting from 0
|
|
||||||
SinglyLinkedListNode* index(int i) const;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* accepts an additional item into the singly 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
|
|
||||||
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(SinglyLinkedListNode* predecessor, const int& inserted_item); // insert an item after given node
|
|
||||||
void erase_successor_to(SinglyLinkedListNode* predecessor); // remove the item after given node
|
|
||||||
|
|
||||||
|
void clear() { while(!this->empty()) this->dequeue(); } // remove all the items from the list
|
||||||
~SinglyLinkedList() { this->clear(); }
|
~SinglyLinkedList() { this->clear(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Loading…
Reference in New Issue
Block a user