How is a Vector of Vector aligned in memory? - c++
I understand as Set size of vector of vectors at run time
describes, one can declare vector of vector as
vector<vector<int> > ref;
then resize the first level by
ref.resize(i);
and push element at the 2nd level:
ref[i].push_back(23);
But how are vector of vector aligned in memory?
For simple vector, it's a container and align its element continuously, like an array; but in the case of vector of vector, I couldn't see the picture.
As the size of each inner vector (the vector in vector of vector) size might change, does the outer vector of vector (the vector in vector of vector) align inner vectors continously? Does the outer vector researve memeory space for each inner vector? what if one vector overshoot?
The size of the vector<int> struct that is stored in ref is constant. Common implementations has this as three pointers, or around 12 bytes on 32-bit architectures, or 24 bytes on shiny new 64-bit architectures.
So ref manages roughly ref.capacity() * 12 bytes of continuous storage.
Each element/vector<int> in ref manages its own integers independent of the elements ref manages. In the artistic rendering below ref.size() == ref.capacity() for the sake of simplicity.
So your
ref.resize(i);
only affects the top row. Your
ref[i].push_back(23);
only affects the i-th column.
vector<vector <int>> m;
The inner vector or rows are implemented as independent
objects on the free store.
Elements in each row are compactly stored, capable of performing dynamic allocation through push_back and resizing.
It is not necessary for each inner vector in the vector< vector<int> > to have the same size. So, the inner-vectors (not their elements) are not stored contiguously. That means, the first element of m[i] is not stored in the address immediately next to the last element of m[i-1].
does the outer vector of vector (the vector in vector of vector) align inner vectors continously?
No. See point#2
Does the outer vector researve memeory space for each inner vector?
No. See point#1. you need to resize or do push_back into inner vector.
how are vector of vector aligned in memory?
vector<T> vec;
consumes this much memory
sizeof(vector<T>) + (vec.size() ∗ sizeof(T))
where,
sizeof(vector<T>) = 12 bytes
and T is vector<int> for a vector of vector.
So, the memory consumed for a 3-by-4 vector<vector<int>> would be.
= sizeof(vector<vector<int>>) + (vec.size() * sizeof(vector<int>))
= 12 + 3 * 12
= 48
what if one vector overshoot?
vector.resize function corrupting memory when size is too large
A vector<vector<int>> could look like this in memory:
+-+-+-+
|b|e|c| vector<vector<int>
+-+-+-+
| | |
| | +-------------------+
| | |
| +---------------+ |
| | |
V V V
+-+-+-+-+-+-+-+-+-+
|b|e|c|b|e|c|b|e|c| 3x vector<int>
+-+-+-+-+-+-+-+-+-+
| | | | | | | | |
| | | | | | | | +-------------+
| | | | | | | | |
| | | | | | | +-------+ |
| | | | | | | | |
| | | | | | V V V
| | | | | |+-+-+-+-+-+
| | | | | ||i|i|i|i|i| 5x int
| | | | | |+-+-+-+-+-+
| | | | | |
| | | | +-+---+
| | | | |
| | | V V
| | |+-+-+-+-+
| | ||i|i|i|i| 4x int
| | |+-+-+-+-+
| | |
| +-+-----------+
| |
V V
+-+-+-+-+-+-+-+-+
|i|i|i|i|i|i|i|i| 8x int
+-+-+-+-+-+-+-+-+
Here b denotes the begin() poiner, e denotes the end() pointer and c denotes the capacity() pointer.
You see, that the rows are not contiguous in memory as you would expect from a matrix structure. Every vector (inner and outer vectors) takes care of it's own memory allocations. The outer vector does not care about what it's elements are doing.
Related
Will a Fibonacci heap be optimal for my task on hierarchical clustering?
I am working on a class project that deals with image segmentation. Given an initial oversegmentation of the image, we are planning to merge pairs together via agglomerative clustering. We will firstly iterate through clusters and push the pair-wise distance and the ID of these pairs of clusters (used for referencing when updating distance due to a merge operation) into a data structure. At each iteration, the pair of clusters with the minimum distance will be merged and the node that stores this distance will be deleted. All other nodes that were originally connected to said pair will have their distance recomputed and information updated (i.e. it is now connected to cluster a-b instead of cluster a). We have been advised to use a Fibonacci heap as it can find the minimum key in O(1). However, because there is still the issue of searching for neighbors and updating their distances, I was wondering if Boost's implementation of Fibonacci heaps allows me to locate a certain node in O(1) if I have a label for each node? TLDR: I'd like to know if there is a data structure that can efficiently locate nodes and delete min.
According to a summary made by John Ahlgren of an SO q&a about performance of std containers : +------------------+---------------------+---------------------+---------------------+------------------+----------------------+ | Container | Insertion | Access | Erase | Find | Persistent Iterators | +------------------+---------------------+---------------------+---------------------+------------------+----------------------+ | vector / string | Back: O(1) or O(n) | O(1) | Back: O(1) | Sorted: O(log n) | No | | | Other: O(n) | | Other: O(n) | Other: O(n) | | +------------------+---------------------+---------------------+---------------------+------------------+----------------------+ | deque | Back/Front: O(1) | O(1) | Back/Front: O(1) | Sorted: O(log n) | Pointers only | | | Other: O(n) | | Other: O(n) | Other: O(n) | | +------------------+---------------------+---------------------+---------------------+------------------+----------------------+ | list | Back/Front: O(1) | Back/Front: O(1) | Back/Front: O(1) | O(n) | Yes | | forward_list | With iterator: O(1) | With iterator: O(1) | With iterator: O(1) | | | | | Index: O(n) | Index: O(n) | Index: O(n) | | | +------------------+---------------------+---------------------+---------------------+------------------+----------------------+ | set / map | O(log n) | N/A | O(log n) | O(log n) | Yes | +------------------+---------------------+---------------------+---------------------+------------------+----------------------+ | unordered_set | O(1) or O(n) | O(1) or O(n) | O(1) or O(n) | O(1) or O(n) | Pointers only | | unordered_map | | | | | | +------------------+---------------------+---------------------+---------------------+------------------+----------------------+ | priority_queue | O(log n) | O(1) | O(log n) | N/A | N/A | +------------------+---------------------+---------------------+---------------------+------------------+----------------------+
Get confused with this declaration - int (*(*foo)(double))[3]
I am lost in this declaration - int (*(*foo)(double))[3]; My understanding is that this is an array with size 3 which element is a function pointer taking double and returning pointer to int. However, the correct explanation seems to be "pointer to function taking double and returning pointer to array of 3 int". The returning pointer to array of 3 int confuses me a lot as int and [3] far apart. Why is that? What is the syntax or rule to declare variables like this complex?
You just read from the inside out remembering that postfix array ([]) and function "call" (()) bind tighter than prefix pointer (*): (*foo) // foo is a pointer... (*foo)(double) // to a function taking a double... (*(*foo)(double)) // returning a pointer... (*(*foo)(double))[3] // to an array of 3... int (*(*foo)(double))[3]; // ints (To work out where to start you might want to work from the outside in, but you need to read back from the inside out to read the declaration in the conventional order.)
You can use "clockwise spiral rule" +----------------------------------+ | +---------------------------+ | | | +--------------------+ | | | | | +----+ | | | | | | |+--+| | | | | | | |^ || | | | int ( * ( *foo)( double ) [3 ]; | ^ ^ ^ ^ || | | | | | | | +---+| | | | | | | +------+ | | | | | +------------------------+ | | | +------------------------------+ | +-------------------------------------+ Thus, Identifier foo is a pointer to function taking double as argument returning pointer to array 3 of int
Union of rectangles in a 2d tiled world
I am trying to find the bounding polygon of a set of adjacent cells(row,col) ( convertable to rectangles) in a 2d tiled world. Processing the cells in a for loop and using the neighbourhood property of the adjacent cells I could eliminate all internal edges and store the rest of the edges. The edges are stored in std::vector; Now I need to merge the edges where there is a common vertex and slope is the same. After merging the edges I need to make the bounding polygon, starting from a vertex going counter clockwise. Please help to find a method to make it possible.
I think this is a simple algorithm to achieve that. Consider we have this as input: | | | | | | -+---+---+---+---+---+- | | | | | | -+---+---+---+---+---+- | | | a | | | -+---+---+---+---+---+- | | b | c | d | | -+---+---+---+---+---+- | | | e | | | -+---+---+---+---+---+- | | | | | | Where a, b, c, d, and e are our input tiles stored as a vector of pairs (Coordinates): std::vector<std::pair<unsigned,unsigned>> tiles; What we want is this: | | | | | | -+---+---+---+---+---+- | | | | | | -+---+---*---*---+---+- | | | | | | -+---*---* *---*---+- | | | | -+---*---* *---*---+- | | | | | | -+---+---*---*---+---+- | | | | | | The algorithm works as follows: Build an array of booleans enclosing the entire set of tiles. You have to trasverse the set to find the bounds of that rectangle. Set as true the positions of the array which represent a tile of the set, and as false otherwise. The output in the example will be (T is true and f is false): +---+---+---+ | f | T | f | +---+---+---+ | T | T | T | +---+---+---+ | f | T | f ] +---+---+---+ Now you have to traverse the border of the hull polygon. Start at the first element marked as true in the flag array and trasverse the vertices in the same direction until you reach the first vertex again, using this rules: If the two tiles in front of the current direction/position are false, turn clockwise and add the vertex to the output list (polygon): (* are vertices added to the polygon, X the current vertex, the arrow the current direction) +---+---+---+ | f | f | f | *---+---X---+ ---> | T | T | f | *---+---+---+ | f | T | f ] +---+---+---+ goes to +---+---+---+ | f | f | f | | *---+---*---+ | | T | T | f | v *---+---X---+ | f | T | f ] +---+---+---+ If one tile is false and one true, go in the same direction (Note that true-false or false-true means you are in a border): +---+---+---+ | f | f | f | | *---+---*---+ | | T | T | f | v *---+---X---+ | f | T | f ] +---+---+---+ goes to +---+---+---+ | f | f | f | | *---+---*---+ | | T | T | f | v *---+---+---+ | f | T | f ] +---+---X---+ If both tiles are true, turn counter-clockwise and add the vertex to the output list (Note that true-true means you have reached part of the set of tiles, a "wall"): +---+---+---+ | f | f | f | | *---+---*---+ | | T | T | f | v *---+---X---+ | f | T | T ] +---+---+---+ goes to +---+---+---+ | f | f | f | +---+---*---+ | T | T | f | ---> +---+---*---X | f | T | T ] +---+---+---+ Considerations: tilemap coordinates vs flag-array coordinates The flag-array represents the rectangle region of the tilemap where the tiles are placed. So the tilemap-coordinates of its first element (tile) is (left,top) where left is the minimum x-coordinate of the selected set of tiles, and top is the minimum y-coordinate of the selected set of tiles. In the second step of the agorithm, you trasverse the frontier (border) of the set of tiles, using the array as a guide. Note that what you really trasverse is that array, so you have to translate the coordinates from flag-coordinates (logical coordinates) to tilemap-coordinates (physical coordinates) to store the vertices of the polygon. Of course thats easy. Also note that the algorithm abstract steps trasverse vertices of edges (physical tile coordinates), not logical-coordinates. You have to be sure what "I'm in that vertex" means and what "advance" and "turn" mean in terms of flag-array coordinates. Border conditions and the front-tiles check We have defined three rules to advance along the border of the set of tiles. We have used the flag-array as a guide to decide what to do (Advance, turn clockwise, or turn counter-clockwise). Note that when the current vertex is in the border of the array, you could (you should) consider that it have neighbour tiles with a false value. For example: +---+---+---+ | f | f | f | | *---+---*---+ | | T | T | f | v *---+---+---+ | f | T | f ] +---+---X---+ goes to +---+---+---+ | f | f | f | *---+---*---+ <-- | T | T | f | *---+---+---+ | f | T | f ] +---X---*---+ exactly as if it was this: +---+---+---+ | f | f | f | | *---+---*---+ | | T | T | f | v *---+---+---+ | f | T | f ] +---+---X---+ | f | f | f | *---*---*---+ Possible optimisations The first step computes the flag array because the algorithm takes the set of tiles selected as a vector. If your tile engine supports it, you could add a property to the tiles (bool selected) and pass the tilemap directly, avoiding the computation and the vertex cooordinates transformations. Example Given this flag-array: +---+---+---+ | T | f | f | +---+---+---+ | T | T | T | +---+---+---+ | f | T | T | +---+---+---+ The execution works as follows (Note that the drawings are the state AFTER the execution of the step): Find the first true tile. In this case (0,0). So we start at one of its vertex (bottom-left vertex, looking upwards, for example. Note that because its the first true tile, you could use that vertex being sure that it belongs to the polygon. So add that first vertex to the polygon): Current position: (0,1) Polygon: {(0,1)} +---+---+---+ ^ | T | f | f | | X---+---+---+ | | T | T | T | +---+---+---+ | f | T | T | +---+---+---+ Start the trasverse. In this case, the front tiles are false-true, so advance: Current position: (0,0) Polygon: {(0,1)} X---+---+---+ ^ | T | f | f | | *---+---+---+ | | T | T | T | +---+---+---+ | f | T | T | +---+---+---+ The front tiles are false-false (We are in a border), so turn clockwise and add the vertex: Current position: (1,0) Polygon: {(0,1),(0,0)} *---X---+---+ | T | f | f | *---+---+---+ | T | T | T | ---> +---+---+---+ | f | T | T | +---+---+---+ Now the fron-tiles are false-false (One is out of the array, and the other is false). turn clockwise and add the vertex: Current position: (1,1) Polygon: {(0,1),(0,0),(1,0)} *---*---+---+ | T | f | f | | *---X---+---+ | | T | T | T | v +---+---+---+ | f | T | T | +---+---+---+ The two front-tiles are true: Turn counter-clockwise and add the vertex: Current position: (1,2) Polygon: {(0,1),(0,0),(1,0),(1,1)} *---*---+---+ | T | f | f | *---*---X---+ | T | T | T | ---> +---+---+---+ | f | T | T | +---+---+---+ One tile is false and the other is true: Advance: Current position: (1,3) Polygon: {(0,1),(0,0),(1,0),(1,1)} *---*---+---+ | T | f | f | *---*---+---X | T | T | T | ---> +---+---+---+ | f | T | T | +---+---+---+ Two false tiles (Both out of array): Turn clockwise and add the vertex: Current position: (2,3) Polygon: {(0,1),(0,0),(1,0),(1,1),(3,1)} *---*---+---+ | T | f | f | | *---*---+---* | | T | T | T | v +---+---+---X | f | T | T | +---+---+---+ One true and one false(Out of array): Advance: Current position: (3,3) Polygon: {(0,1),(0,0),(1,0),(1,1),(3,1)} *---*---+---+ | T | f | f | | *---*---+---* | | T | T | T | v +---+---+---+ | f | T | T | +---+---+---X Two false(Out of array) front-tiles: Turn clockwise and add the vertex: Current position: (2,3) Polygon: {(0,1),(0,0),(1,0),(1,1),(3,1),(3,3)} *---*---+---+ | T | f | f | *---*---+---* | T | T | T | <--- +---+---+---+ | f | T | T | +---+---X---* true-false (One true and one out of bounds): Advance: Current position: (1,3) Polygon: {(0,1),(0,0),(1,0),(1,1),(3,1),(3,3)} *---*---+---+ | T | f | f | *---*---+---* | T | T | T | <--- +---+---+---+ | f | T | T | +---X---+---* false-false (One false and one out of bounds): Turn clockwise and add the vertex: Current position: (1,2) Polygon: {(0,1),(0,0),(1,0),(1,1),(3,1),(3,3),(1,3)} *---*---+---+ | T | f | f | ^ *---*---+---* | | T | T | T | | +---X---+---+ | f | T | T | +---*---+---* true-true front-tiles: Turn counter-clockwise and add the vertex: Current position: (0,2) Polygon: {(0,1),(0,0),(1,0),(1,1),(3,1),(3,3),(1,3),(1,2)} *---*---+---+ | T | f | f | *---*---+---* | T | T | T | <--- X---*---+---+ | f | T | T | +---*---+---* false-false front-tiles: Turn clockwise and add the vertex: Current position: (0,1) Polygon: {(0,1),(0,0),(1,0),(1,1),(3,1),(3,3),(1,3),(1,2),(0,2)} *---*---+---+ | T | f | f | ^ X---*---+---* | | T | T | T | | *---*---+---+ | f | T | T | +---*---+---* The current vertex is the first vertex of the polygon: The execution have finished. The result is as follows: Polygon: {(0,1),(0,0),(1,0),(1,1),(3,1),(3,3),(1,3),(1,2),(0,2)} *---* | | * *-------* | | *---* | | | *-------*
Because of tiles, this is a 'special case' of finding boundary polygon. I would go with some simple approach. Tile (x,y) consist of vertices [(x,y), (x+1,y), (x+1,y+1), (x,y+1)]. Vertex is a part of boundary polygon if it is in 1, 2 or 3 tiles. To find vertices on boundary it is enough to count number of tiles it is in. For that it is enough to pass through tiles and increment vertex appearance count for tile 4 vertices. Vertices with tile count 1, 2 or 3 are on the boundary polygon. To order vertices it is enough to start from some vertex on a boundary and look for a neighbouring vertex that is also on a boundary. To traverse vertices in same direction it is important to take a care of direction order of neighbouring vertices to check. E.g. if last vertex is on -x, than order of directions to check is +y, +x, -y. Since direction of last edge is known, if next edge is in the same direction than that vertex is for a removal. If region is simple connected, than removal can be known also from tile count. If tile count of a vertex is 2 than vertex is for removal. For now we don't have guarantee that order is clockwise. That can be check by checking (some of) upper-most edge(s) is it in clockwise direction. If it is not, than reverse polygon.
check whether if two squares are intersecting with each other [duplicate]
This question already has answers here: Determine if two rectangles overlap each other? (21 answers) Closed 9 years ago. I would like to check if two square are intersecting with each other. My idea is this for (i = 0; i < 4; i++) for (j = 0; j < 4; j++) { bool x = check line(i) of first square intersect with line (j) of the second square if (x) return; } any idea to optimize this code?
You don't have to loop through all coordinates to check if two squares intersect. Here's a simple solution which will work as long as the squares are not rotated. Say that you represent a square by its top left corner coordinate and its side length. Let aX and aY represent the coordinates and aLen the side length of square A, and vice versa for square B. Then to check if square B intersects with square A evaluate this: (aX < (bX + bLen) && (aX + aLen) > bX) && (aY < (bY - bLen) && (aY - aLen) > bY) In other words, there are four possible scenarios and you check if either of square B's corners are within the X-range of square A and that either of square B's corners are within the Y-range of square A. (Y) ^ | 1: 2: | +--------+ +--------+ | | | | | | | A +--|-----+ +-----+--+ A | | | | | | | | | | | +-----+--+ B | | B +--+-----+ | | | | | | +--------+ +--------+ | | 3: 4: | +--------+ +--------+ | | | | | | | B +--|-----+ +-----+--+ B | | | | | | | | | | | +-----+--+ A | | A +--+-----+ | | | | | | +--------+ +--------+ | +-------------------------------------------------> (X) For more info see this answer of a similar question: Determine if two rectangles overlap each other?
stl::map erase vs std::vector erase behave differently
class CSensor { public: CSensor(int nVal1,char* pVal2,unsigned int nVal3); CSensor(const CSensor& refMessage); const CSensor& operator=(const CSensor& refMessage); ~CSensor(void); private: int m_nVal1; char* m_pVal2; unsigned int m_nVal3; }; // vector erase std::vector<CSensor> SensorList; CSensor obj1(1,"Test1",10); SensorList.push_back(obj1); CSensor obj2(2,"Test2",11); SensorList.push_back(obj2); CSensor obj3(3,"Test3",12); SensorList.push_back(obj3); SensorList.erase (SensorList.begin()+1); // map erase std::map<int ,CSensor> ListSensor; CSensor obj11(1,"Test1",10); CSensor obj12(2,"Test2",11); CSensor obj13(3,"Test3",12); ListSensor.insert(std::pair<int,CSensor>(1,obj11)); ListSensor.insert(std::pair<int,CSensor>(2,obj12)); ListSensor.insert(std::pair<int,CSensor>(3,obj13)); ListSensor.erase(2); I debugged both the case. In both the cases i am deleting the second element.In case of vector it is copying 3 element to 2nd poition and than it it deleting the 3 rd location. So when u say List.erase (List.begin()+1); it is calling assignment operator(CSensor=) and then calling destructor. In case of map when i do ListSensor.erase(2); it only calls the destructor. I have gone through STL vector vs map erase. It talks Iterator,couldn't explain the behavior. My question is why erase behaves differently for these two STL container??
This is not a behaviour of .erase per se, but a consequence of how each respective container works. Deleting from a vector When you delete from a vector (List is a really poor name for a vector, btw), its contents must be shuffled along to fill the gap because the elements of a vector are always stored contiguously in memory. This is generally done by copying (or moving) elements then chopping off the remainder: Vector elements in memory: +---+---+---+---+---+---+---+---+---+ | a | b | c | d | e | f | g | h | i | +---+---+---+---+---+---+---+---+---+ Erase 'e': +---+---+---+---+---+---+---+---+---+ | a | b | c | d | | f | g | h | i | +---+---+---+---+---+---+---+---+---+ Fill the gap by copying/moving across: <-- +---+---+---+---+---+---+---+---+---+ | a | b | c | d | f | f | g | h | i | +---+---+---+---+---+---+---+---+---+ <-- +---+---+---+---+---+---+---+---+---+ | a | b | c | d | f | g | g | h | i | +---+---+---+---+---+---+---+---+---+ <-- +---+---+---+---+---+---+---+---+---+ | a | b | c | d | f | g | h | h | i | +---+---+---+---+---+---+---+---+---+ <-- +---+---+---+---+---+---+---+---+---+ | a | b | c | d | f | g | h | i | i | +---+---+---+---+---+---+---+---+---+ Resize the container: +---+---+---+---+---+---+---+---+ | a | b | c | d | f | g | h | i | +---+---+---+---+---+---+---+---+ Deleting from a map This is not the case for a map, whose contents are not necessarily stored contiguously in memory (in fact, the complexity requirements mean it's almost always a tree structure filled with pointers to discontiguous data).
This is one reason to have different containers! The vector has to copy the elements following the eased element to cover the "hole" that it left. Otherwise the elements wouldn't be contiguous anymore. The map holds its elements in a tree structure and just has to adjust some pointers to rebalance the tree. To the vector's defense: Copying a couple of elements might be cheaper than allocating tree nodes separately and keeping the tree balanced. There are always tradeoffs!