I need to init a 2-dim array of forward_list after I read its sizes from input.
class Foo{
forward_list<int> * koo;
int A, B;
void boo(){
scanf("%d",&A);
scanf("%d",&B);
koo = new forward_list<int>[A][B];
koo[0][0] = 1;
}
};
Compiler:
cannot convert ‘std::forward_list<int> (*)[1]’ to ‘std::forward_list<int>*’ in assignment adjList = new forward_list<int>[A][A];
CLion IDE: Subscribed value is not an array (at koo[0])
I don't do much C++ so I don't quite know what's wrong. How can I do this right? I need to access all forward_list in O(1), and would, therefore, prefer arrays or generally something fast.
Btw: not sure if this is called dynamic initialization, let me know if I should change the title.
Thanks.
A forward_list is incapable of reaching your performance requirement: "I need to access all forward_list in O(1)" you can see that in a comparision here: https://en.wikipedia.org/wiki/Linked_list#Linked_lists_vs._dynamic_arrays You can see that Indexing for a forward_list and other linked list variants is O(n).
The simplest container type that does provide the O(1) indexing you're looking for is a vector or another of the dynamic array variants. I believe your current needs could be satisfied by doing something like:
vector<vector<int>> koo(A, vector<int>(B));
It should be mentioned that while this will satisfy your performance requirements, a vector of vectors isn't a great solution; but you can look at it as a good stopgap solution.
Related
I am new to stl and i came across a question where it is required to store a lot of pairs having same characteristics (like:- (string,int)) together. Can we store pairs in array and if so how? Thanks in advance..
You can try something like:
struct demo
{
string str;
int i;
};
std::array<demo, 5> arr; //for fixed size array of 5 elements
std::vector<demo> vec; //for dynamic size arrays
You want ...
to store a lot of pairs having same characteristics
The terminology is a bit wrong. You want to store many pairs of the same type (not "characteristics").
You could define your own struct as answered by Nipun, or use
std::array<std::pair<std::string,int>, 10> arr;
for an array of 10 pairs of strings and ints.
Spend more time on reading a documentation on standard containers and standard utilities. Perhaps you want some other existing thing (e.g. std::set with std::tuple, maybe with your own comparator).
Templates can (and often should) be combined since they are compositional. Be also aware of the rule of five.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I'm looking for data structure where I can stores multiple vectors in one vector without risking fragmentation or any performance issues.
Now doing this
std::vector< std::vector<SomeType> > myMultiVector;
would help, but for my understanding the memory gets fragmented because obviously every vector within myMultiVector will not lie in a contiguous space, because of its allocation scheme.
This is not for creating arrays where I know the dimensions or sizes from the start. The sizes are dynamic in all directions. What I want is a structure like that one, in which the allocated size is contiguous. I want to be able to do something like push_back() and resize() on the vector of vectors and every vector itself. The size of the vectors should be able to differ.
I have been taking a look at Boost::Multiarray. Seems promising, but don't want an array, I want something where dyanmic. I'm still not sure, though I can change sizes in the dimensions if it does that by an efficient way. So maybe Boost::Multiarray is the answer for that.
I also have been thinking about using std::multimap or even std::unordered_multimap and use the key as index, because of the interal sorting and hashing I'm not sure if it the right structure though the allocation space should be contiguous.
Using std::vector< std::vector > myMultiVector; works for what I need but I feel there is a missed oportunity for optimization.
What other Alternatives do you know which could help providing a more efficient vector of vectors? Let me know :-)
NOTE: I know the question is quite similar to others asked here. I'm only asking for alternatives not quite for the solution of a particular problem.
It sounds like the different things you want exclude each other. If you want to have a size-flexibility in each of the subvectors and at the same time have all the data nicely aligned in the memory you are basically forced to reallocate memory for all vectors and do a lot of copying each time you change the size of any of the subvectors. Thus probably it's a better idea to stay with the std::vector< std::vector<SomeType> >. If you need to do a lot of efficient operations with a fixed size of the vectors between every resize operation, you could think of creating an intermediate array into which you copy all your data.
You should also think about whether your concerns about performance have an effect in practice. Unless you notice that using std::vector< std::vector<SomeType> > does actually influence your performance significantly you should maybe not worry about it.
So to directly answer your question: I think there probably is no better data type for your needs, because the one you suggested is already totally fine.
If you're careful about using it, you could always implement a 1D vector as a 2D one using functors:
template <typename T>
class Vector2D : public std::vector<T>
{
protected:
unsigned _width;
public:
unsigned width() {return _width;}
void setWidth(unsigned i) {width = i;}
T& operator()(int x, int y) {
return this->operator[](x + _width * y);
}
Vector2D(unsigned newWidth = 10) : std::vector<T>(), _width(newWidth) {}
};
Which allows you to do things like:
int main() {
Vector2D<int> vec(10);
vec.resize(100, 0);
vec(6, 7) = 3;
int some_number = vec(6, 7);
cout << some_number: //Output: 3
}
The advantage of this approach is that the data is contiguous, yet can be manipulated with 2-dimensional semantics.
std::multimap / std::unordered_multimap will certainly not do what you want. Each individual SomeType will be in it's own allocation (much worse than a vector of vectors).
I don't think you will find a pre-built type that does what you want - you are going to have write it yourself (possibly by wrapping a single std::vector, and then providing smart iterators which understand the range of this particular vector). Note that my_magic.front().push_back(...) will have to insert into the middle of your backing vector, and shuffle everything up (although vector::insert will do the shuffling for you).
Personally, I would be surprised if it was worth it.
I would suggest using your own container. I am going to give you an abstract Idea:
class MyOwn2D{
MyOwn2D(int rows,int cols):rows(rows),cols(cols),data(std::vector<SomeType>(rows*cols){}
SomeType& get_element(int i,int j){
return data[i*rows+j];
}
private:
int rows,cols
std::vector<SomeType> data;
};
The previous example is so dummy. You need something much better with operators overloading and you may need a proxy to do [][] operator (to more like 2D array). So, I was just proposing the idea of it. Good Luck!
I have been reading up on C++ lately, especially STL, and I decided to do the Knights Tour problem again. I'm thinking about the best way to implement this, and I'm looking for some help.
Just for fun and practice, I thought I'd start with a "Piece" base class, which a "Knight" class can inherit from. I want to do this so I later can try adding other pieces(even though most of the pieces can't walk over the whole board and complete the problem).
So the "piece class" will need some sort of container to store the coordinates of the piece on the board and the number of moves it has made in that specific step.
I'm thinking I need a linked list with 64 (8 * 8) places to do this most efficiently, containing x,y and moves.
Looking at the STL containers, I can't find anything except map that will hold more than one type.
What can I do to store the coordinate pair and an int for the number of moves in one container? Are there more efficient ways of doing this than using vector, list or map? Do I need a custom container?
Thanks!
You can use
struct CellInfo
{
int x, y, move_count;
}
And store it in std::vector for constant access.
Apart from STL and encapsulation, a very efficient way is to use arrays:
pair<int, int> piece_pos[N];
int piece_move[N];
This avoids the overhead of memory leakage and is faster than dynamic allocation.
If you stell want to use STL, then:
vector<pair<int, int> > piece_pos(N);
vector<int> piece(N);
The C++ STL now has static arrays as well. If you want to store the number of times a given x,y coordinate has been moved to, you can create an array of arrays like the following:
using container_type = std::array<std::array<int, 8>, 8>;
// ...
container_type c;
int moves = c[x][y]; // constant-time access.
If you don't need to look moves up based on x,y, and just want the data stored efficiently, use a flat array of size 8x8 = 64.
If your compiler is out of date, consider using std::vector instead.
I ran into some trouble while using a list of arrays.
So to clear things up I do know that I can't have a std::list containing arrays.
I am using boost::array to be able to do that.
Currently I prototype all datatypes needed for my pathfinding algorithm and test them for speed and cache coherence.
typedef boost::array<int,2> VertexB2i;
typedef std::list<VertexB2i> VertexList;
These types are not used for pathfinding, they are simply easier to use then all the real c++ arrays and flags for the pathfinder, so they are just used to generate a navigation mesh.
(I also know I could use a stl::pair instead boost::array in this case, but I want to keep the generated data as similar to the pathfinders data as possible, so I don't have to deal with two totally different interfaces the whole time)
VertexList* vl = new VertexList();
vl->push_back({{8,28}}); // this does not work, why?
So while setting up some testing data for these two data-types, I noticed that the commented line does not work, although this does work:
VertexList* vl = new VertexList();
VertexB2i ver1 = {{8,28}};
vl->push_back({ver1}); // works
So to sum it up:
Is there anyway to pushback a "VertexB2i" without declaring it separte first?
General advices?
std::array (or boost::array) is an aggregate type. In C++98/03 it can only be initialized in the declarator:
std::array<int, 2> arr = { 1, 2 };
thelist.push_back(arr); // makes a copy
In C++11, you can use uniform initialization to create temporaries as well:
std::list<std::array<int,2>> l;
l.push_back(std::array<int,2>{{2,3}}); // maybe copy
l.emplace_back(std::array<int,2>{{2,3}}); // maybe copy, probably optimized out
I have an array of 1000-2000 elements which are pointers to objects. I want to keep my array sorted and obviously I want to do this as quick as possible. They are sorted by a member and not allocated contiguously so assume a cache miss whenever I access the sort-by member.
Currently I'm sorting on-demand rather than on-add, but because of the cache misses and [presumably] non-inlining of the member access the inner loop of my quick sort is slow.
I'm doing tests and trying things now, (and see what the actual bottleneck is) but can anyone recommend a good alternative to speeding this up?
Should I do an insert-sort instead of quicksorting on-demand, or should I try and change my model to make the elements contigious and reduce cache misses?
OR, is there a sort algorithm I've not come accross which is good for data that is going to cache miss?
Edit: Maybe I worded this wrong :), I don't actually need my array sorted all the time (I'm not iterating through them sequentially for anything) I just need it sorted when I'm doing a binary chop to find a matching object, and doing that quicksort at that time (when I want to search) is currently my bottleneck, because of the cache misses and jumps (I'm using a < operator on my object, but I'm hoping that inlines in release)
Simple approach: insertion sort on every insert. Since your elements are not aligned in memory I'm guessing linked list. If so, then you could transform it into a linked list with jumps to the 10th element, the 100th and so on. This is kind of similar to the next suggestion.
Or you reorganize your container structure into a binary tree (or what every tree you like, B, B*, red-black, ...) and insert elements like you would insert them into a search tree.
Running a quicksort on each insertion is enormously inefficient. Doing a binary search and insert operation would likely be orders of magnitude faster. Using a binary search tree instead of a linear array would reduce the insert cost.
Edit: I missed that you were doing sort on extraction, not insert. Regardless, keeping things sorted amortizes sorting time over each insert, which almost has to be a win, unless you have a lot of inserts for each extraction.
If you want to keep the sort on-extract methodology, then maybe switch to merge sort, or another sort that has good performance for mostly-sorted data.
I think the best approach in your case would be changing your data structure to something logarithmic and rethinking your architecture. Because the bottleneck of your application is not that sorting thing, but the question why do you have to sort everything on each insert and try to compensate that by adding on-demand sort?.
Another thing you could try (that is based on your current implementation) is implementing an external pointer - something mapping table / function and sort those second keys, but I actually doubt it would benefit in this case.
Instead of the array of the pointers you may consider an array of structs which consist of both a pointer to your object and the sort criteria. That is:
Instead of
struct MyType {
// ...
int m_SomeField; // this is the sort criteria
};
std::vector<MyType*> arr;
You may do this:
strcut ArrayElement {
MyType* m_pObj; // the actual object
int m_SortCriteria; // should be always equal to the m_pObj->m_SomeField
};
std::vector<ArrayElement> arr;
You may also remove the m_SomeField field from your struct, if you only access your object via this array.
By such in order to sort your array you won't need to dereference m_pObj every iteration. Hence you'll utilize the cache.
Of course you must keep the m_SortCriteria always synchronized with m_SomeField of the object (in case you're editing it).
As you mention, you're going to have to do some profiling to determine if this is a bottleneck and if other approaches provide any relief.
Alternatives to using an array are std::set or std::multiset which are normally implemented as R-B binary trees, and so have good performance for most applications. You're going to have to weigh using them against the frequency of the sort-when-searched pattern you implemented.
In either case, I wouldn't recommend rolling-your-own sort or search unless you're interested in learning more about how it's done.
I would think that sorting on insertion would be better. We are talking O(log N) comparisons here, so say ceil( O(log N) ) + 1 retrieval of the data to sort with.
For 2000, it amounts to: 8
What's great about this is that you can buffer the data of the element to be inserted, that's how you only have 8 function calls to actually insert.
You may wish to look at some inlining, but do profile before you're sure THIS is the tight spot.
Nowadays you could use a set, either a std::set, if you have unique values in your structure member, or, std::multiset if you have duplicate values in you structure member.
One side note: The concept using pointers, is in general not advisable.
STL containers (if used correctly) give you nearly always an optimized performance.
Anyway. Please see some example code:
#include <iostream>
#include <array>
#include <algorithm>
#include <set>
#include <iterator>
// Demo data structure, whatever
struct Data {
int i{};
};
// -----------------------------------------------------------------------------------------
// All in the below section is executed during compile time. Not during runtime
// It will create an array to some thousands pointer
constexpr std::size_t DemoSize = 4000u;
using DemoPtrData = std::array<const Data*, DemoSize>;
using DemoData = std::array<Data, DemoSize>;
consteval DemoData createDemoData() {
DemoData dd{};
int k{};
for (Data& d : dd)
d.i = k++*2;
return dd;
}
constexpr DemoData demoData = createDemoData();
consteval DemoPtrData createDemoPtrData(const DemoData& dd) {
DemoPtrData dpd{};
for (std::size_t k{}; k < dpd.size(); ++k)
dpd[k] = &dd[k];
return dpd;
}
constexpr DemoPtrData dpd = createDemoPtrData(demoData);
// -----------------------------------------------------------------------------------------
struct Comp {bool operator () (const Data* d1, const Data* d2) const { return d1->i < d2->i; }};
using MySet = std::multiset<const Data*, Comp>;
int main() {
// Add some thousand pointers. Will be sorted according to struct member
MySet mySet{ dpd.begin(), dpd.end() };
// Extract a range of data. integer values between 42 and 52
const Data* p42 = dpd[21];
const Data* p52 = dpd[26];
// Show result
for (auto iptr = mySet.lower_bound(p42); iptr != mySet.upper_bound(p52); ++iptr)
std::cout << (*iptr)->i << '\n';
// Insert a new element
Data d1{ 47 };
mySet.insert(&d1);
// Show again
std::cout << "\n\n";
for (auto iptr = mySet.lower_bound(p42); iptr != mySet.upper_bound(p52); ++iptr)
std::cout << (*iptr)->i << '\n';
}