HiveBrain v1.2.0
Get Started
← Back to all entries
patterncppMinor

Double-ended queue and iterators

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
doubleandqueueiteratorsended

Problem

I have created a double-ended container, but I have doubts about its efficiency in terms of performance. Can you please criticize the code? What can be done extra, such as shortening it?

```
#ifndef EXERCISE_H_
#define EXERCISE_H_

#include

typedef unsigned short ushort;

template
class list{
type_t data;
ushort size_;
public:
list head, tail, next, prev;
list();
virtual ~list();

ushort &size();

void setData(type_t);
type_t getData();

virtual void push_back(type_t) = 0;
virtual type_t pop_front() = 0;

virtual void push_front(type_t) = 0;
virtual type_t pop_back() = 0;
virtual type_t front() = 0;
virtual type_t back() = 0;
virtual void print() = 0;

};

// DEFAULT CTOR
template
list::list() : size_(0){ this->head = this->tail = this->next = this->prev = nullptr;}

// DTOR
template
list::~list() {}

template
ushort & list::size(){
return size_;
}

template
void list::setData(type_t value){
this->data = value;
}

template
type_t list::getData(){
return this->data;
}

/*\
* DEQUEUE CLASS
\*/

template
class dequeue : public list {
public:
void push_back(type_t);
type_t pop_front();

void push_front(type_t);
type_t pop_back();

type_t front();
type_t back();
void print();
};

// PUSH_BACK func
template
void dequeue::push_back(type_t value){
list * item = new dequeue;
if (!item) throw std::bad_alloc();

item->setData(value);

if (this->tail) {
this->tail->next = item;
item->prev = this->tail;
}
this->tail = item;
++this->size();
if (!this->head) this->head = this->tail;
}

// POP_BACK func
template
type_t dequeue::pop_back(){
if(!this->head) throw std::out_of_range("List is empty");

list * item;
type_t value;

if(this->tail && this->tail != this->head){
item = this->tail;
value = this->tail->getData();
this->tail = this->

Solution

-
I really recommend using an explicit type for your linked-list node:

template
struct linked_list_node 
{
    T datum;
    linked_list_node* next;
    linked_list_node* prev;
}


Then, in your actual dequeue class you would have:

linked_list_node* head;
linked_list_node* tail;
size_t size;


-
Returning the size as a reference is a no-no: the caller may assign some nonsensical value to it, which will break the invariants of your dequeue.

-
When it comes to terminology, "dequeue" is actually called deque (double-ended queue). Dequeue is a canonical name for the operation of removing and returning the head node in a FIFO queue data structure.

-
Your print function is a bit ad-hoc. There are two better options:

  • Override template std::ostream& operator&)



-
Add iterators. After doing that, you can use:

std::copy(dec.begin(), dec.end(), std::ostream_iterator(cout, ", "));


-
In your deque type, don't forget to delete all elements in its destructor.

Code Snippets

template<typename T>
struct linked_list_node 
{
    T datum;
    linked_list_node<T>* next;
    linked_list_node<T>* prev;
}
linked_list_node<T>* head;
linked_list_node<T>* tail;
size_t size;
std::copy(dec.begin(), dec.end(), std::ostream_iterator<T>(cout, ", "));

Context

StackExchange Code Review Q#151482, answer score: 8

Revisions (0)

No revisions yet.