opprenskning
This commit is contained in:
parent
56cdc9248b
commit
45e01074bb
@ -2,8 +2,8 @@
|
|||||||
#define DOUBLY_LINKED_LIST_H
|
#define DOUBLY_LINKED_LIST_H
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <cstddef>
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
#include "sequence.h"
|
|
||||||
|
|
||||||
namespace seq
|
namespace seq
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "queue.h"
|
||||||
#include "dynamic-array.h"
|
#include "dynamic-array.h"
|
||||||
|
|
||||||
using namespace seq;
|
using namespace seq;
|
||||||
@ -14,7 +16,6 @@ void DynamicArray::clear()
|
|||||||
this->capacity = 0;
|
this->capacity = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert an item at index i
|
|
||||||
void DynamicArray::enqueue(int value)
|
void DynamicArray::enqueue(int value)
|
||||||
{
|
{
|
||||||
int i = this->logical_size;
|
int i = this->logical_size;
|
||||||
@ -40,7 +41,7 @@ void DynamicArray::enqueue(int value)
|
|||||||
|
|
||||||
// copy all of temp_storage into values[i+1] to values[logical_size]
|
// copy all of temp_storage into values[i+1] to values[logical_size]
|
||||||
std::copy(temp_storage, temp_storage + shifted_elements, &this->values[i+1]);
|
std::copy(temp_storage, temp_storage + shifted_elements, &this->values[i+1]);
|
||||||
delete temp_storage;
|
delete[] temp_storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
// now we can write the inserted item into values[i]
|
// now we can write the inserted item into values[i]
|
||||||
@ -48,29 +49,35 @@ void DynamicArray::enqueue(int value)
|
|||||||
this->values[i] = value;
|
this->values[i] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove the item at index i
|
|
||||||
int DynamicArray::dequeue()
|
int DynamicArray::dequeue()
|
||||||
{
|
{
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
// shift all elements from index i+1 onward one to the left
|
if (this->size() == 0) {
|
||||||
// we use a temporary storage and copy() from <algorithm> to do this efficiently
|
return 0;
|
||||||
size_t shifted_elements = this->logical_size - i - 1;
|
|
||||||
if(shifted_elements > 0)
|
|
||||||
{
|
|
||||||
int* temp_storage = new int[shifted_elements]();
|
|
||||||
|
|
||||||
// copy values[i+1] to values[logical_size-1] into temp_storage
|
|
||||||
std::copy(this->values + i+1, this->values + this->logical_size, temp_storage);
|
|
||||||
|
|
||||||
// copy all of temp_storage into values[i] to values[logical_size-2]
|
|
||||||
std::copy(temp_storage, temp_storage + shifted_elements, &this->values[i]);
|
|
||||||
delete temp_storage;
|
|
||||||
}
|
}
|
||||||
this->logical_size--; // with this, we are done with the task
|
int i = 0;
|
||||||
|
// Save the first element wich we want to return:
|
||||||
|
int outgoing = this->values[0];
|
||||||
|
|
||||||
// now let us see whether we have deleted so many items that we should resize to save memory
|
// shift all elements from onward one to the left
|
||||||
if(this->capacity/2 >= this->logical_size) this->resize(this->capacity/2);
|
size_t shifted_elements = this->logical_size - 1;
|
||||||
|
|
||||||
|
int* temp_storage = new int[shifted_elements]();
|
||||||
|
|
||||||
|
// copy values[i+1] to values[logical_size-1] into temp_storage
|
||||||
|
std::copy(this->values + 1, this->values + this->logical_size, temp_storage);
|
||||||
|
|
||||||
|
// copy all of temp_storage into values[i] to values[logical_size-2]
|
||||||
|
std::copy(temp_storage, temp_storage + shifted_elements, &this->values[i]);
|
||||||
|
delete[] temp_storage;
|
||||||
|
if (!this->empty()) {
|
||||||
|
this->logical_size--; // with this, we are done with the task
|
||||||
|
|
||||||
|
// now let us see whether we have deleted so many items that we should resize to save memory
|
||||||
|
if(this->capacity/2 >= this->logical_size) this->resize(this->capacity/2);
|
||||||
|
|
||||||
|
}
|
||||||
|
return outgoing;
|
||||||
}
|
}
|
||||||
|
|
||||||
// allocate static array with "new_capacity" elements,
|
// allocate static array with "new_capacity" elements,
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
#include "sequence.h"
|
|
||||||
|
|
||||||
namespace seq
|
namespace seq
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
#include "dynamic-array.h"
|
#include "dynamic-array.h"
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
@ -12,11 +13,19 @@ namespace
|
|||||||
/*
|
/*
|
||||||
* run a simple test
|
* run a simple test
|
||||||
*/
|
*/
|
||||||
void test_sequence(seq::Queue* sqn, int n, int m, std::ostream* os)
|
void test_queue(seq::Queue* sqn, int n, int m, std::ostream* os)
|
||||||
{
|
{
|
||||||
assert((m > 0) && (n > m));
|
assert((m > 0) && (n > m));
|
||||||
if(os) *os << "Enqueue 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->enqueue(2*i);
|
for(int i = 0; i < n; i++) sqn->enqueue(2*i);
|
||||||
|
for(int i = 0; i < n; i++) sqn->dequeue();
|
||||||
|
}
|
||||||
|
void test_queue(std::queue<int>* sqn, int n, int m, std::ostream* os)
|
||||||
|
{
|
||||||
|
assert((m > 0) && (n > m));
|
||||||
|
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->pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -24,16 +33,38 @@ namespace
|
|||||||
*/
|
*/
|
||||||
float test_with_time_measurement(seq::Queue* sqn, int iterations)
|
float test_with_time_measurement(seq::Queue* sqn, int iterations)
|
||||||
{
|
{
|
||||||
int sequence_length = 200001;
|
int queue_length = 20001;
|
||||||
int deletions = 10;
|
int deletions = 10;
|
||||||
test_sequence(sqn, sequence_length, deletions, &std::cout);
|
test_queue(sqn, queue_length, deletions, &std::cout);
|
||||||
|
|
||||||
int log_entries = 10;
|
int log_entries = 10;
|
||||||
std::cout << "\nNow repeat the above " << iterations << " times:\n";
|
std::cout << "\nNow repeat the above " << iterations << " times:\n";
|
||||||
auto t0 = std::chrono::high_resolution_clock::now();
|
auto t0 = std::chrono::high_resolution_clock::now();
|
||||||
for(int i = 0; i < iterations; i++)
|
for(int i = 0; i < iterations; i++)
|
||||||
{
|
{
|
||||||
test_sequence(sqn, sequence_length, deletions, nullptr);
|
test_queue(sqn, queue_length, deletions, nullptr);
|
||||||
|
if((i+1) % (iterations/log_entries) == 0)
|
||||||
|
{
|
||||||
|
std::cout << "\t" << i+1 << "\n";
|
||||||
|
std::cout.flush(); // make sure that status output is shown without delay
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto t1 = std::chrono::high_resolution_clock::now();
|
||||||
|
return 1.0e-06 * std::chrono::duration_cast<std::chrono::microseconds>(t1-t0).count();
|
||||||
|
}
|
||||||
|
|
||||||
|
float test_with_time_measurement(std::queue<int>* sqn, int iterations)
|
||||||
|
{
|
||||||
|
int queue_length = 20001;
|
||||||
|
int deletions = 10;
|
||||||
|
test_queue(sqn, queue_length, deletions, &std::cout);
|
||||||
|
|
||||||
|
int log_entries = 10;
|
||||||
|
std::cout << "\nNow repeat the above " << iterations << " times:\n";
|
||||||
|
auto t0 = std::chrono::high_resolution_clock::now();
|
||||||
|
for(int i = 0; i < iterations; i++)
|
||||||
|
{
|
||||||
|
test_queue(sqn, queue_length, deletions, nullptr);
|
||||||
if((i+1) % (iterations/log_entries) == 0)
|
if((i+1) % (iterations/log_entries) == 0)
|
||||||
{
|
{
|
||||||
std::cout << "\t" << i+1 << "\n";
|
std::cout << "\t" << i+1 << "\n";
|
||||||
@ -61,7 +92,12 @@ int main()
|
|||||||
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\n*** test with std::queue ***\n";
|
||||||
|
std::queue<int> queue;
|
||||||
|
float queue_time = test_with_time_measurement(&queue, 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";
|
||||||
|
std::cout << "Runtime for std::queue:\t" << queue_time << " s\n";
|
||||||
}
|
}
|
||||||
|
@ -1,42 +0,0 @@
|
|||||||
#ifndef SEQUENCE_H
|
|
||||||
#define SEQUENCE_H
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
namespace seq
|
|
||||||
{
|
|
||||||
class Sequence
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual bool empty() const = 0; // test whether the sequence is empty
|
|
||||||
virtual size_t size() const = 0; // return the size (number of items in the sequence)
|
|
||||||
|
|
||||||
// it is the caller's responsibility to ensure that the sequence is not empty when calling front() or back()!
|
|
||||||
virtual int& front() = 0; // return a reference to the first item
|
|
||||||
virtual int& back() = 0; // return a reference to the final item
|
|
||||||
|
|
||||||
// return a reference to the item at position i of the sequence, counting from 0
|
|
||||||
// it is the caller's responsibility that the index is within range
|
|
||||||
virtual int& at(int i) = 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* accepts an additional item into the sequence (front or back);
|
|
||||||
* the pushed item is passed by reference, but a copy of it is stored in the Sequence
|
|
||||||
* the Sequence takes ownership of the copy (but not of the original!)
|
|
||||||
*/
|
|
||||||
virtual void push(const int& pushed_item) = 0; // default push operation (front or back)
|
|
||||||
virtual void push_front(const int& pushed_item) = 0;
|
|
||||||
virtual void push_back(const int& pushed_item) = 0;
|
|
||||||
|
|
||||||
virtual void pop() = 0; // default pop operation (front or back)
|
|
||||||
virtual void pop_front() = 0; // remove the first element
|
|
||||||
virtual void pop_back() = 0; // remove the last element
|
|
||||||
virtual void clear() = 0; // remove all the items from the sequence
|
|
||||||
|
|
||||||
// it is the caller's responsibility that the index is within range
|
|
||||||
virtual void insert_at(int i, const int& inserted_item) = 0; // insert an item at index i
|
|
||||||
virtual void erase_at(int i) = 0; // remove the item at index i
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,5 +1,5 @@
|
|||||||
|
#include <cstddef>
|
||||||
#include "singly-linked-list.h"
|
#include "singly-linked-list.h"
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
using namespace seq;
|
using namespace seq;
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
#define SINGLY_LINKED_LIST_H
|
#define SINGLY_LINKED_LIST_H
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include "sequence.h"
|
|
||||||
#include "queue.h"
|
#include "queue.h"
|
||||||
|
|
||||||
namespace seq
|
namespace seq
|
||||||
@ -36,7 +35,7 @@ namespace seq
|
|||||||
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)
|
||||||
|
|
||||||
void enqueue(int element);
|
void enqueue(int value);
|
||||||
int dequeue();
|
int dequeue();
|
||||||
|
|
||||||
void clear() { while(!this->empty()) this->dequeue(); } // remove all the items from the list
|
void clear() { while(!this->empty()) this->dequeue(); } // remove all the items from the list
|
||||||
|
Loading…
Reference in New Issue
Block a user