Container of fixed size where older elements will be deleted - c++

Is there container adaptor in std or Poco that allows to specify size of it and where I can push element and in case if it will be full new element will be added in place of older one (or will be added at the end but first element will be deleted and all rest elements will be moved on one position back).
For instance imagine that container with size = 3.
I am pushing 4 elements [1, 2, 3, 4] consequentially into it and as a result I am getting that container with [2, 3, 4] or [4, 2, 3].

the structure you're looking for is called a circular buffer. C++ doesn't offer a container that represents that kind of structure, but it can be written pretty easily when you use a vector as the underlaying container.
In order to get an idea of how to actually implement it, you could look here, where the OP asked about a similar structure, but operating on bools. The only difference between your problem and his is that you actually need a templated class, so it would look something like this:
template <typename T>
class circularBuffer {
vector<T> data;
unsigned int lastEntryPos;
// methods to access "data"
};
You could also add a second template parameter indicating the size of the underlaying vector, and set it in the constructor:
template <typename T, size_type size>
class circularBuffer {
// ...
circularBuffer(): data(size), lastEntryPos(0){};
};

you can use a container list or vector, then before insert element, check container's size, if meet the count, popup old element, then push new one.
each time, you can iterate list in reverse sequence to get the element as their insert sequence.
#include <iostream>
#include <string>
#include <list>
using namespace std;
int main()
{
list<int> q;
for(int m = 0; m < 10; m++)
{
if(q.size() < 3)
q.push_front(m);
else
{
q.pop_back();
q.push_front(m);
}
}
for(auto x = q.rbegin(); x != q.rend(); x++)
std::cout << *x;
return 0;
}
output 789

Related

Create a vector of pairs, where the second element of a pair points to the next pair in the vector

I need to create a vector or similar list of pairs, where the first element of a pair is of class T, and the second element is a pointer to the next pair.
Illustration
template<class T>
std::vector<std::pair<T, T*>> createPointingVector(std::vector<T> vec) {
std::vector<std::pair<T, T*>> new_vec;
for (int i=0; i<vec.size(); i++){
new_vec.push_back(std::make_pair(vec[i], &(vec[i - 1])));
}
return new_vec;
}
I understand that std::vector<std::pair<T, T*>> is incorrect because the second element of the pair is not supposed to be of type *T but rather a recursive *std::pair<T, *std::pair<T, *std::pair<T, ...>>>.
Is it possible to fix my code or what are the other ways to achieve my goal, if any?
I strongly recommend rethinking using a bare vector.
My reason for that is that you need to guarantee that that the memory of the vector is never reallocated. Note that you also should in any case make sure that your vector is made sure to allocate all required memory from the start, either by initializing with empty elements or by using std::vector::reserve.
Otherwise, if you have a pointer already set and then change the capacity of the vector, the pointer becomes invalid, a good setup if you want undefined behaviour.
Therefore I strongly advise you to use a wrapper class around your vector, which makes sure no capacity change is ever called.
Now, if you do that, the thing is, why do you use actual pointers?
Consider using data of type std::vector<std::pair<T, size_t> >, with the second entry actually storing the position within the vector, rather than an actual pointer:
template<class T>
class PointingVector
{
public:
PointingVector(const std::vector<T>& vec);
private:
std::vector<std::pair<T, size_t> > data;
};
template<class T>
PointingVector<T>::PointingVector(const std::vector<T>& vec)
{
for (int i=0; i<vec.size()-1; i++)
{
data.push_back(std::make_pair(vec[i], i+1));
}
data.push_back(std::make_pair(vec.back(), 0)); // assuming that the last points to the first
}
After that, make sure that every additional method you add leaves the pointing consistent. Like should you write something similar to erase, make sure that all pairs are updated accordingly.
And the analogy to dereferencing is trivial:
template<class T>
std::pair<T, size_t>& PointingVector<T>::get(size_t index)
{
return data[index];
}
The important thing about my solution is that you can exclude possible bugs in regard to dangling pointers. Those are really bad, especially since they might not cause an error in test executions, given the nature of undefined behaviour. Worst thing in my solution is that the indices are wrong after calling a method that has a bug.
And if you want to introduce anything that changes the capacity of the vector, no problem, no need to redo any pointers. Just make sure the indices are changed accordingly. If you did this with pointers, your first step would probably be to create a list of indices anyway, so why not work with one directly.
Plus, as this solution has no (visible) pointers at all, you don't need to do any memory management.
Another solution: Ditch std::pair and define your own type:
template<class T>
struct Node
{
T data;
Node* next; // or a smart pointer type
Node(const T& data, Node* next) : data(data), next(next) {}
};
Then build up your vector like this:
template<class T>
std::vector<Node<T>*> createPointingVector(const std::vector<T>& vec)
{
std::vector<Node<T>*> new_vec;
for (int i=0; i<vec.size(); i++)
{
new_vec.push_back(new Node<T>(vec[i], nullptr));
}
for (int i=0; i<vec.size()-1; i++)
{
new_vec[i]->next = new_vec[i+1];
}
new_vec[vec.size()-1]->next = new_vec[0];
return new_vec;
}
Note that without smart pointers, you need to do memory management. I'd consider making next a weak_ptr<Node>, and have the vector be over shared_ptr<Node>. That way, the memory is automatically deallocated as soon as the vector gets deleted (assuming you have no other pointers active).
What you ask is doable, but according to the illustration found linked within your answer, the pointers should point one-up circularly inside the input vector, and not one-down, as is in your code example. What I mean is:
new_vec[0] = {vec[0], &vec[1]}
new_vec[1] = {vec[1], &vec[2]}
...
new_vec[N-1] = {vec[N-1], &vec[0]}
above, N = vec.size().
I attach a minimum working example:
#include <iostream>
#include <vector>
#include <utility> // std::pair, std::make_pair
template<class T>
std::vector<std::pair<T, T*> > createPointingVector(std::vector<T>& vec) { // important: make the parameter a reference
std::vector<std::pair<T, T*> > new_vec;
int vec_size = vec.size();
for (int i = 0; i < vec_size-1; i++)
new_vec.push_back( std::make_pair( vec[i], &(vec[i + 1]) ) ); // pointers assigned according to linked picture
new_vec.push_back( std::make_pair( vec[vec_size-1], &vec[0] ) );
return new_vec;
}
int main()
{
std::vector<int> input = {1,2,3,4};
std::vector<std::pair<int,int*> > sol = createPointingVector(input);
for (auto i : sol)
std::cout << i.first << " -> " << *(i.second) << std::endl;
return 0;
}

cannot access the vector members of a class

I have tried to access the members of a class Part that are vector elements of type integer inside the vector tasks.
#include <iostream>
#include <vector>
using namespace std;
class Part{
vector<int> tasks;
public:
void setTasks(void);
void getTasks(void);
};
void Part::setTasks(void){
vector<int>::iterator it;
int i=1;
for (it = this->tasks.begin(); it != this->tasks.end(); ++it)
{
*it=i;
i=i+1;
}
}
void Part::getTasks(void){
vector<int>::iterator it;
for (it = this->tasks.begin(); it != this->tasks.end(); ++it)
cout<<*it<<"\t";
}
int main()
{
Part one;
one.setTasks();
one.getTasks();
return 0;
}
I am simply trying to access the values and print them yet failing. There is no compilation error. In run-time, nothing is outputted in the terminal. Where is the error?
A default constructed vector has zero size, so the for loop in setTasks is never entered (since the begin() and end() iterators are the same at that point). If you set an initial size to the vector your code will work as intended. For instance, try adding the following at the beginning of setTasks
tasks.resize(10); // sets vector size to 10 elements, each initialized to 0
Another way to write that function would be
#include <numeric>
...
void Part::setTasks(void){
tasks.resize(10);
std::iota(tasks.begin(), tasks.end(), 1); // requires C++11
}
You could also set the initial size of the vector in the default constructor of Part if you wanted to. In that case add the following public constructor
Part() : tasks(10)
{}
Yet another way to achieve setting the size upon construction would be
class Part{
vector<int> tasks = vector<int>(10); // requires C++11
The size of your vector is 0 when you call setTasks(). Your iterator doesn't get you into the for loop at all. You need to think about what exactly you want your setTasks() to do. How many elements of the vector did you intend to set? You should either define your vector with that size, or use that many number of push_backs instead to set your vector to the desired value.
Your vector is empty. Try giving it a size. For example, vector<int> tasks(10). See option 3 in this.
Alternatively, you can use a "back-insert" iterator (#include <iterator>), which internally calls std::vector::push_back, like this:
void Part::setTasks(void){
auto back_it = std::back_inserter(tasks);
for(int i = 0; i < 10; ++i)
*back_it++ = i;
}
This kind of iterator is especially useful in algorithms where your destination size is unknown. Although if you know the size in advance, you should use reserve/resize or specify the size at construction, since push-ing back into a vector can sometimes be slow due to re-allocation.

How to pass a vector to another vector push back? (without creating a extra variable to pass)

Well I am questioning myself if there is a way to pass a vector directly in a parameter, with that I mean, like this:
int xPOS = 5, yPOS = 6, zPOS = 2;
//^this is actually a struct but
//I simplified the code to this
std::vector <std::vector<int>> NodePoints;
NodePoints.push_back(
std::vector<int> {xPOS,yPOS,zPOS}
);
This code ofcourse gives an error; typename not allowed, and expected a ')'
I would have used a struct, but I have to pass the data to a Abstract Virtual Machine where I need to access the node positions as Array[index][index] like:
public GPS_WhenRouteIsCalculated(...)
{
for(new i = 0; i < amount_of_nodes; ++i)
{
printf("Point(%d)=NodeID(%d), Position(X;Y;Z):{%f;%f;%f}",i,node_id_array[i],NodePosition[i][0],NodePosition[i][1],NodePosition[i][2]);
}
return 1;
}
Ofcourse I could do it like this:
std::vector <std::vector<int>> NodePoints;//global
std::vector<int> x;//local
x.push_back(xPOS);
x.push_back(yPOS);
x.push_back(zPOS);
NodePoints.push_back(x);
or this:
std::vector <std::vector<int>> NodePoints;//global
std::vector<int> x;//global
x.push_back(xPOS);
x.push_back(yPOS);
x.push_back(zPOS);
NodePoints.push_back(x);
x.clear()
but then I'm wondering which of the two would be faster/more efficient/better?
Or is there a way to get my initial code working (first snippet)?
Use C++11, or something from boost for this (also you can use simple v.push_back({1,2,3}), vector will be constructed from initializer_list).
http://liveworkspace.org/code/m4kRJ$0
You can use boost::assign as well, if you have no C++11.
#include <vector>
#include <boost/assign/list_of.hpp>
using namespace boost::assign;
int main()
{
std::vector<std::vector<int>> v;
v.push_back(list_of(1)(2)(3));
}
http://liveworkspace.org/code/m4kRJ$5
and of course you can use old variant
int ptr[1,2,3];
v.push_back(std::vector<int>(ptr, ptr + sizeof(ptr) / sizeof(*ptr));
If you don't have access to either Boost or C++11 then you could consider quite a simple solution based around a class. By wrapping a vector to store your three points within a class with some simple access controls, you can create the flexibility you need. First create the class:
class NodePoint
{
public:
NodePoint( int a, int b, int c )
{
dim_.push_back( a );
dim_.push_back( b );
dim_.push_back( c );
}
int& operator[]( size_t i ){ return dim_[i]; }
private:
vector<int> dim_;
};
The important thing here is to encapsulate the vector as an aggregate of the object. The NodePoint can only be initialised by providing the three points. I've also provided operator[] to allow indexed access to the object. It can be used as follows:
NodePoint a(5, 6, 2);
cout << a[0] << " " << a[1] << " " << a[2] << endl;
Which prints:
5 6 2
Note that this will of course throw if an attempt is made to access an out of bounds index point but that's still better than a fixed array which would most likely seg fault. I don't see this as a perfect solution but it should get you reasonably safely to where you want to be.
If your main goal is to avoid unnecessary copies of vector<> then here how you should deal with it.
C++03
Insert an empty vector into the nested vector (e.g. Nodepoints) and then use std::swap() or std::vector::swap() upon it.
NodePoints.push_back(std::vector<int>()); // add an empty vector
std::swap(x, NodePoints.back()); // swaps contents of `x` and last element of `NodePoints`
So after the swap(), the contents of x will be transferred to NodePoints.back() without any copying.
C++11
Use std::move() to avoid extra copies
NodePoints.push_back(std::move(x)); // #include<utility>
Here is the explanation of std::move and here is an example.
Both of the above solutions have somewhat similar effect.

Erasing elements of Deque container

I want to erase the elements of a deque. When you have a deque that contain structs and you want to print the elements from back to front, but you don't want to print elements that have the same struct elements how do you do it?
I have a struct like this:
struct New_Array {
array<array<int,4>,4> mytable;
int h;
};
The deque is filled with elements from a previous procedure.
You want to print all the elements that are in the deque, but each table you print must have a unique "h". Only the first table you find with a specific "h" must be printed, the other tables with the same "h" should not be printed. I think this can be also inplemented with a "find" function.
The value of "h" that we will find starting from the back of the deque will be 0 and it will increase its value towards the front of the deque.
I have tried this:
void Find_Solution_Path(deque<New_Array> Mydeque)
{
while(Mydeque.size()>0)
{
New_Array y=Mydeque.back();
PrintBoard(y); //this is a function that prints the 4x4 array.
Mydeque.pop_back();
for(unsigned int i=0; i<Mydeque.size(); i++)
{
New_Array xxx=Mydeque[i];
if(xxx.h==y.h)
{
Mydeque.erase(Mydeque[i]);
}
}
}
}
I would not use a deque but a set. If you absolutely need the deque, create a set none the less. Define a < operator with an appropriate criterion < reflecting the uniqueness. You insert each printed element into the set. Before printing you check if the element is already present in the set (find).
HTH, Martin
One way is to use std::unique_copy.
#include <iostream>
#include <algorithm>
#include <iterator>
#include <deque>
struct New_Array {
array<array<int,4>,4> mytable;
int h;
// unique_copy needs this:
bool operator==(const New_Array& other) { return h == other.h; }
};
ostream& operator<<(ostream& out, const New_Array& v)
{
return out << v.h;
}
int main()
{
std::deque<New_Array> q;
New_Array temp;
// {1, 1, 2, 2, 3, 3}
temp.h = 1;
q.push_back(temp);
q.push_back(temp);
temp.h = 2;
q.push_back(temp);
q.push_back(temp);
temp.h = 3;
q.push_back(temp);
q.push_back(temp);
unique_copy(q.begin(), q.end(), ostream_iterator<New_Array>(cout, "\n"));
}
The range needs to be sorted for unique_copy to work properly. Sorting isn't needed in above case since we inserted elements in order.
I believe #Martin answer is probably the best solution. If you cannot change the signature for the function returning a deque, you can just construct a set from it and all the duplicates will automatically go away:
// First you need to declare a compare function for NewArray objects
struct NewArrayComp {
bool operator()(const NewArray& a1, const NewArray& a2) const {
return a1.h < a2.h;
}
};
// Then you can construct a set from the deque
deque<NewArray> dq;
// ...
std::set<NewArray, NewArrayComp> s(dq.begin(), dq.end());
// Finally you can just print the arrays (without duplicates)
for (const auto& a : s)
PrintBoard(a);
This solution has a O(n log n) complexity, while your code is O(n^2).
Additionally, if you do not want to pay the cost of duplicating the elements from the deque into the set you can use move semantics in C++11:
std::set<NewArray, NewArrayComp> s;
std::move(dq.begin(), dq.end(), std::inserter(s, s.begin()));
This will just move all the elements without making copies of them.

Understanding boost::disjoint_sets

I need to use boost::disjoint_sets, but the documentation is unclear to me. Can someone please explain what each template parameter means, and perhaps give a small example code for creating a disjoint_sets?
As per the request, I am using disjoint_sets to implement Tarjan's off-line least common ancestors algorithm, i.e - the value type should be vertex_descriptor.
What I can understand from the documentation :
Disjoint need to associate a rank and a parent (in the forest tree) to each element. Since you might want to work with any kind of data you may,for example, not always want to use a map for the parent: with integer an array is sufficient. You also need a rank foe each element (the rank needed for the union-find).
You'll need two "properties" :
one to associate an integer to each element (first template argument), the rank
one to associate an element to an other one (second template argument), the fathers
On an example :
std::vector<int> rank (100);
std::vector<int> parent (100);
boost::disjoint_sets<int*,int*> ds(&rank[0], &parent[0]);
Arrays are used &rank[0], &parent[0] to the type in the template is int*
For a more complex example (using maps) you can look at Ugo's answer.
You are just giving to the algorithm two structures to store the data (rank/parent) he needs.
disjoint_sets<Rank, Parent, FindCompress>
Rank PropertyMap used to store the size of a set (element -> std::size_t). See union by rank
Parent PropertyMap used to store the parent of an element (element -> element). See Path compression
FindCompress Optional argument defining the find method. Default to find_with_full_path_compression See here (Default should be what you need).
Example:
template <typename Rank, typename Parent>
void algo(Rank& r, Parent& p, std::vector<Element>& elements)
{
boost::disjoint_sets<Rank,Parent> dsets(r, p);
for (std::vector<Element>::iterator e = elements.begin();
e != elements.end(); e++)
dsets.make_set(*e);
...
}
int main()
{
std::vector<Element> elements;
elements.push_back(Element(...));
...
typedef std::map<Element,std::size_t> rank_t; // => order on Element
typedef std::map<Element,Element> parent_t;
rank_t rank_map;
parent_t parent_map;
boost::associative_property_map<rank_t> rank_pmap(rank_map);
boost::associative_property_map<parent_t> parent_pmap(parent_map);
algo(rank_pmap, parent_pmap, elements);
}
Note that "The Boost Property Map Library contains a few adaptors that convert commonly used data-structures that implement a mapping operation, such as builtin arrays (pointers), iterators, and std::map, to have the property map interface"
This list of these adaptors (like boost::associative_property_map) can be found here.
For those of you who can't afford the overhead of std::map (or can't use it because you don't have default constructor in your class), but whose data is not as simple as int, I wrote a guide to a solution using std::vector, which is kind of optimal when you know the total number of elements beforehand.
The guide includes a fully-working sample code that you can download and test on your own.
The solution mentioned there assumes you have control of the class' code so that in particular you can add some attributes. If this is still not possible, you can always add a wrapper around it:
class Wrapper {
UntouchableClass const& mInstance;
size_t dsID;
size_t dsRank;
size_t dsParent;
}
Moreover, if you know the number of elements to be small, there's no need for size_t, in which case you can add some template for the UnsignedInt type and decide in runtime to instantiate it with uint8_t, uint16_t, uint32_tor uint64_t, which you can obtain with <cstdint> in C++11 or with boost::cstdint otherwise.
template <typename UnsignedInt>
class Wrapper {
UntouchableClass const& mInstance;
UnsignedInt dsID;
UnsignedInt dsRank;
UnsignedInt dsParent;
}
Here's the link again in case you missed it: http://janoma.cl/post/using-disjoint-sets-with-a-vector/
I written a simple implementation a while ago. Have a look.
struct DisjointSet {
vector<int> parent;
vector<int> size;
DisjointSet(int maxSize) {
parent.resize(maxSize);
size.resize(maxSize);
for (int i = 0; i < maxSize; i++) {
parent[i] = i;
size[i] = 1;
}
}
int find_set(int v) {
if (v == parent[v])
return v;
return parent[v] = find_set(parent[v]);
}
void union_set(int a, int b) {
a = find_set(a);
b = find_set(b);
if (a != b) {
if (size[a] < size[b])
swap(a, b);
parent[b] = a;
size[a] += size[b];
}
}
};
And the usage goes like this. It's simple. Isn't it?
void solve() {
int n;
cin >> n;
DisjointSet S(n); // Initializing with maximum Size
S.union_set(1, 2);
S.union_set(3, 7);
int parent = S.find_set(1); // root of 1
}
Loic's answer looks good to me, but I needed to initialize the parent so that each element had itself as parent, so I used the iota function to generate an increasing sequence starting from 0.
Using Boost, and I imported bits/stdc++.h and used using namespace std for simplicity.
#include <bits/stdc++.h>
#include <boost/pending/disjoint_sets.hpp>
#include <boost/unordered/unordered_set.hpp>
using namespace std;
int main() {
array<int, 100> rank;
array<int, 100> parent;
iota(parent.begin(), parent.end(), 0);
boost::disjoint_sets<int*, int*> ds(rank.begin(), parent.begin());
ds.union_set(1, 2);
ds.union_set(1, 3);
ds.union_set(1, 4);
cout << ds.find_set(1) << endl; // 1 or 2 or 3 or 4
cout << ds.find_set(2) << endl; // 1 or 2 or 3 or 4
cout << ds.find_set(3) << endl; // 1 or 2 or 3 or 4
cout << ds.find_set(4) << endl; // 1 or 2 or 3 or 4
cout << ds.find_set(5) << endl; // 5
cout << ds.find_set(6) << endl; // 6
}
I changed std::vector to std::array because pushing elements to a vector will make it realloc its data, which makes the references the disjoint sets object contains become invalid.
As far as I know, it's not guaranteed that the parent will be a specific number, so that's why I wrote 1 or 2 or 3 or 4 (it can be any of these). Maybe the documentation explains with more detail which number will be chosen as leader of the set (I haven't studied it).
In my case, the output is:
2
2
2
2
5
6
Seems simple, it can probably be improved to make it more robust (somehow).
Note: std::iota Fills the range [first, last) with sequentially increasing values, starting with value and repetitively evaluating ++value.
More: https://en.cppreference.com/w/cpp/algorithm/iota