Reputation: 309
I'm trying to select the appropriate data type for a new project to fit the following requirements:
ex. let's say 1,2,3,4,5,6 inserted into the container. After some time 6 will be deleted and 7 will be inserted so the list would be 7,1,2,3,4,5 and then 5 will deleted etc... but the size must be same.
I was wondering which data structure will be the most efficient and suitable one for my situtation from performance and memory point of view.
Thanks...
edit: by the way its a little bit different froö the basic FIFO logic because lets say we create 10 elements (size) data container but inserted only 3 elements even it has not reach the end of the container(limit of the size), if the specified time passed it would be deleted.
By the way i was thinking about to use boost:array but a little bit confused about std:vector and std:deque. Is there any specific advantage in this situtaion?
Upvotes: 2
Views: 1635
Reputation: 1806
We all know from our data structures and algorithm classes that where inserts and deletes are likely we should use a linked list of some sort. It might be that what we know is wrong though.
Modern memory is blisteringly fast copying huge chunks of data around (so you shouldn't worry as much as you think about copying data around) and uses caching for linear searches (which a linked list structure will effectively defeat). These two factors combined may well mean you should use a good old vector or boost::array.
But don't take my word for it, here's Bjarn Stroustrup explaining it all.
Upvotes: 0
Reputation: 114481
The fastest solution for this is a statically-allocated array where you handle the queue yourself using head/tail/count; for example
#define MAX_NUMBER_OF_ELEMENTS 10
// Use statically-allocated memory
unsigned char raw_buf[MAX_NUMBER_OF_ELEMENTS * sizeof(X)];
X * const buf = (X *)&raw_buf[0];
int head, tail, count;
// Returns the address for a new element on the queue
inline void *add_element_address() {
void *p = &buf[head];
if (++head == MAX_NUMBER_OF_ELEMENTS) head = 0;
count++;
return p;
}
// Removes oldest element from the queue
inline void remove_element() {
buf[tail].~X();
if (++tail == MAX_NUMBER_OF_ELEMENTS) tail = 0;
count--;
}
// Get the n-th element from the queue where 0 is the
// last added element and count-1 is the oldest one.
X& element(int index) {
index = head - index - 1;
if (index < 0) index += MAX_NUMBER_OF_ELEMENTS;
return buf[index];
}
void add_element(... constructor arguments ...) {
new (add_element_address()) X(... constructor arguments ...);
}
With this approach the buffer will be at a fixed address in memory (thus also freeing a register) and no copy of any kind is needed on the objects (they're constructed directly in place using placement new). Adding, removing and indexed access operations are all O(1)
.
Upvotes: 0
Reputation: 9413
You need std::queue backed by std::vector with some fixed capacity:
std::vector<YourType> underlying_storage(capacity);
std::queue<YourType, std::vector<YourType>> queue(std::move(underlying_storage));
// Now your queue is backed up by vector with predefined capacity
Upvotes: 0
Reputation: 2228
What you need is a cyclic buffer build on fixed-size array, this is very simple and the fastest data structure.
You can write your own cyclic buffer class or try to use boost implementation of cyclic buffer http://www.boost.org/doc/libs/1_54_0/libs/circular_buffer/doc/circular_buffer.html
Upvotes: 6
Reputation: 361
Looks like you need a queue, probably backed up by some optimized fixed-size container with FIFO support.
Upvotes: 1