I have a 2d Array of Vectors declared as
Vector<int> v1[10][11];
and I want to accessing the elements inside the array. Would I treat the 2d array of vectors as a 3d array and access elements like this:
v1[9][10][0];
to access the first element of the last member of the array?
std::vector allows the [] operator, but I'm pretty sure your [9][10][0] is going to be out of bounds - you don't have anything there.
Assuming that you're opting for an array something like
[0 1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
...
100 101 102 103 104 105 106 107 108 109]
then the last element is going to be v1[9][10], corresponding to 109 in the picture.
If you want each element to be an array, I think you'll need
std::vector<int[sizeofarray]> v1[10][11];
//or just vector<int[size]> v1[10][11]; if using namespace std;
Related
I am working on the second part of an assignment which asks me to reorder a matrix such that each row is in monotonically increasing order and so that the first element of each row is monotonically increasing. If two rows have the same initial value, the rows should be ordered by the second element in the row. If those are both the same, it should be the third element, continuing through the last element.
I have written a bubble sort that works fine for the first part (reordering each row). I have written a bubble sort for the second part (making sure that the first element of each row is monotonically increasing). However, I am running into an infinite loop and I do not understand why.
I do understand that the issue is that my "inorder" variable is not eventually getting set to true (which would end the while loop). However, I do not understand why inorder is not getting set to true. My logic is the following: once the following code has swapped rows to the point that the rows are all in order, we will pass through the while loop one more time (and inorder will get set to true), which will cause the while loop to end. I am stumped as to why this isn't happening.
inorder = .false.
loopA: do while ( .not. inorder ) !While the rows are not ordered
inorder = .true.
loopB: do i = 1, rows-1 !Iterate through the first column of the array
if (arr(i,1)>arr(i+1,1)) then !If we find a row that is out of order
inorder = .false.
tempArr = arr(i+1,:) !Swap the corresponding rows
arr(i+1,:) = arr(i,:)
arr(i,:) = tempArr
end if
if (arr(i,1)==arr(i+1,1)) then !The first elements of the rows are the same
loopC: do j=2, cols !Iterate through the rest of the row to find the first element that is not the same
if (arr(i,j)>arr(i+1,j)) then !Found elements that are not the same and that are out of order
inorder = .false.
tempArr = arr(i+1,:) !Swap the corresponding rows
arr(i+1,:) = arr(i,:)
arr(i,:) = tempArr
end if
end do loopC
end if
end do loopB
end do loopA
Example input:
6 3 9 23 80
7 54 78 87 87
83 5 67 8 23
102 1 67 54 34
78 3 45 67 28
14 33 24 34 9
Example (correct) output (that my code is not generating):
1 34 54 67 102
3 6 9 23 80
3 28 45 67 78
5 8 23 67 83
7 54 78 87 87
9 14 24 33 34
It is also possible that staring at this for hours has made me miss something stupid, so I appreciate any pointers.
When you get to compare rows where the first element is identical, you then go through the whole array and compare every single item.
So if you have two arrays like this:
1 5 3
1 2 4
Then the first element is the same, it enters the second part of your code.
In second place, 5>2, so it swaps it:
1 2 4
1 5 3
But then it doesn't stop. In third place, 4>3, so it swaps it back
1 5 3
1 2 4
And now you're back to where you were.
Cheers
here is my code please tell me why it is not printing from starting as in map it is printing in correct manner
#include<bits/stdc++.h>
using namespace std;
int main(){
unordered_map<int,int>arr;
for(int i=1;i<=10;i++){
arr[i]=i*i;
}
for(auto it=arr.begin();it!=arr.end();it++){
cout<<it->first<<" "<<it->second<<"\n";
}
cout<<"normal map \n";
map<int,int>arry;
for(int i=1;i<=10;i++){
arry[i]=i*i;
}
for(auto it=arry.begin();it!=arry.end();it++){
cout<<it->first<<" "<<it->second<<"\n";
}
}
and my output is
10 100
9 81
8 64
7 49
6 36
5 25
1 1
2 4
3 9
4 16
normal map
1 1
2 4
3 9
4 16
5 25
6 36
7 49
8 64
9 81
10 100
why un_ordered map printing the value in this fashion why not it printing like map
std::unordered_map doesn't order keys in any specific order. This is why it is called unordered.
Internally, the elements are not sorted in any particular order, but organized into buckets. Which bucket an element is placed into depends entirely on the hash of its key. This allows fast access to individual elements, since once the hash is computed, it refers to the exact bucket the element is placed into.
I have created a Fortran array, say
real, dimension(4, 4) :: A
Being a matrix
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
And I want to pass it to a subroutine in form
call MySoubroutine(A(2,2))
And inside my subroutine get this array and modify some of its elements
real, dimension(:), intent(inout) : A
A(1,1) = 91
A(1, 2) = 92
A(2, 1) = 93
A(2, 2) = 94
So after calling the function in my main program the array A is
1 2 3 4
5 91 92 8
9 93 94 12
13 14 15 16
What is the best an most optimum way to achieve such a behaviour?
In detail my questions are:
Is there a better way of using a subarray inside the subroutine?
How shall I declare the array in the subroutine? I want just to pass a pointer to the first element, so may not know the dimension of the subarray.
I need to segment an image, based on a simple rule (if value is in between 2 values). I'm using only STL containers (I'm not using opencv or other libraries because I want to keep this free of dependencies while teaching myself c++)
I've stored my images as vector< vector<double> >. My brute force approach is to iterate through my image using 2 iterators and check each value, and maybe push the indices of the values that satisfy my condition to another vector<int>. I'll have to do this until all segments are found. Every time I want to pick a segment I'll iterate through the stored indices.
What is the correct way to do this?
Can this be achieved in one pass?
What is a suitable STL container for this process? I'm trying to
figure it out through this flowchart. The best I can come up
with was an unordered_multimap.
If you're moving elements to the end of the vector, use std::stable_partition.
std::vector<int> vec(20);
// 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
std::iota(begin(vec), end(vec), 0);
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
std::stable_partition(begin(vec), end(vec),
[](const auto& e){ return (4 <= e && e < 12);});
// 4 5 6 7 8 9 10 11 0 1 2 3 12 13 14 15 16 17 18 19
Online example here.
This will also work if you store the data in a single vector - use iterators for the beginning and end of the column/row instead of the entire range. I've got no idea how you read 'across' the data sensibly with either a 1D or 2D vector though!
(I wrote a very nice post about Sean Parent's gather algorithm before realising it doesn't answer the question. View the edit history if you want to move selected items to places other than the ends.)
If the image is divided to two segments, you can store the segmentation as vector<vector<bool>> with the same size as the image.
I'm using C++. Using sort from STL is allowed.
I have an array of int, like this :
1 4 1 5 145 345 14 4
The numbers are stored in a char* (i read them from a binary file, 4 bytes per numbers)
I want to do two things with this array :
swap each number with the one after that
4 1 5 1 345 145 4 14
sort it by group of 2
4 1 4 14 5 1 345 145
I could code it step by step, but it wouldn't be efficient. What I'm looking for is speed. O(n log n) would be great.
Also, this array can be bigger than 500MB, so memory usage is an issue.
My first idea was to sort the array starting from the end (to swap the numbers 2 by 2) and treating it as a long* (to force the sorting to take 2 int each time). But I couldn't manage to code it, and I'm not even sure it would work.
I hope I was clear enough, thanks for your help : )
This is the most memory efficient layout I could come up with. Obviously the vector I'm using would be replaced by the data blob you're using, assuming endian-ness is all handled well enough. The premise of the code below is simple.
Generate 1024 random values in pairs, each pair consisting of the first number between 1 and 500, the second number between 1 and 50.
Iterate the entire list, flipping all even-index values with their following odd-index brethren.
Send the entire thing to std::qsort with an item width of two (2) int32_t values and a count of half the original vector.
The comparator function simply sorts on the immediate value first, and on the second value if the first is equal.
The sample below does this for 1024 items. I've tested it without output for 134217728 items (exactly 536870912 bytes) and the results were pretty impressive for a measly macbook air laptop, about 15 seconds, only about 10 of that on the actual sort. What is ideally most important is no additional memory allocation is required beyond the data vector. Yes, to the purists, I do use call-stack space, but only because q-sort does.
I hope you get something out of it.
Note: I only show the first part of the output, but I hope it shows what you're looking for.
#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>
#include <cstdint>
// a most-wacked-out random generator. every other call will
// pull from a rand modulo either the first, or second template
// parameter, in alternation.
template<int N,int M>
struct randN
{
int i = 0;
int32_t operator ()()
{
i = (i+1)%2;
return (i ? rand() % N : rand() % M) + 1;
}
};
// compare to integer values by address.
int pair_cmp(const void* arg1, const void* arg2)
{
const int32_t *left = (const int32_t*)arg1;
const int32_t *right = (const int32_t *)arg2;
return (left[0] == right[0]) ? left[1] - right[1] : left[0] - right[0];
}
int main(int argc, char *argv[])
{
// a crapload of int values
static const size_t N = 1024;
// seed rand()
srand((unsigned)time(0));
// get a huge array of random crap from 1..50
vector<int32_t> data;
data.reserve(N);
std::generate_n(back_inserter(data), N, randN<500,50>());
// flip all the values
for (size_t i=0;i<data.size();i+=2)
{
int32_t tmp = data[i];
data[i] = data[i+1];
data[i+1] = tmp;
}
// now sort in pairs. using qsort only because it lends itself
// *very* nicely to performing block-based sorting.
std::qsort(&data[0], data.size()/2, sizeof(data[0])*2, pair_cmp);
cout << "After sorting..." << endl;
std::copy(data.begin(), data.end(), ostream_iterator<int32_t>(cout,"\n"));
cout << endl << endl;
return EXIT_SUCCESS;
}
Output
After sorting...
1
69
1
83
1
198
1
343
1
367
2
12
2
30
2
135
2
169
2
185
2
284
2
323
2
325
2
347
2
367
2
373
2
382
2
422
2
492
3
286
3
321
3
364
3
377
3
400
3
418
3
441
4
24
4
97
4
153
4
210
4
224
4
250
4
354
4
356
4
386
4
430
5
14
5
26
5
95
5
145
5
302
5
379
5
435
5
436
5
499
6
67
6
104
6
135
6
164
6
179
6
310
6
321
6
399
6
409
6
425
6
467
6
496
7
18
7
65
7
71
7
84
7
116
7
201
7
242
7
251
7
256
7
324
7
325
7
485
8
52
8
93
8
156
8
193
8
285
8
307
8
410
8
456
8
471
9
27
9
116
9
137
9
143
9
190
9
190
9
293
9
419
9
453
With some additional constraints on both your input and your platform, you can probably use an approach like the one you are thinking of. These constraints would include
Your input contains only positive numbers (i.e. can be treated as unsigned)
Your platform provides uint8_t and uint64_t in <cstdint>
You address a single platform with known endianness.
In that case you can divide your input into groups of 8 bytes, do some byte shuffling to arrange each groups as one uint64_t with the "first" number from the input in the lower-valued half and run std::sort on the resulting array. Depending on endianness you may need to do more byte shuffling to rearrange each sorted 8-byte group as a pair of uint32_t in the expected order.
If you can't code this on your own, I'd strongly advise you not to take this approach.
A better and more portable approach (you have some inherent non-portability by starting from a not clearly specified binary file format), would be:
std::vector<int> swap_and_sort_int_pairs(const unsigned char buffer[], size_t buflen) {
const size_t intsz = sizeof(int);
// We have to assume that the binary format in buffer is compatible with our int representation
// we also require an even number of integers
assert(buflen % (2*intsz) == 0);
// load pairwise
std::vector< std::pair<int,int> > pairs;
pairs.reserve(buflen/(2*intsz));
for (const unsigned char* bufp=buffer; bufp<buffer+buflen; bufp+= 2*intsz) {
// It would be better to have a more portable binary -> int conversion
int first_value = *reinterpret_cast<int*>(bufp);
int second_value = *reinterpret_cast<int*>(bufp + intsz);
// swap each pair here
pairs.emplace_back( second_value, firstvalue );
}
// less<pair<..>> does lexicographical ordering, which is what you are looking ofr
std::sort(pairs.begin(), pairs.end());
// convert back to linear vector
std::vector<int> result;
result.reserve(2*pairs.size());
for (auto& entry : pairs) {
result.push_back(entry.first);
result.push_back(entry.second);
}
return result;
}
Both the inital parse/swap pass (which you need anyway) and the final conversion are O(N), so the total complexity is still (O(N log(N)).
If you can continue to work with pairs, you can save the final conversion. The other way to save that conversion would be to use a hand-coded sort with two-int strides and two-int swap: much more work - and possibly still hard to get as efficient as a well-tuned library sort.
Do one thing at a time. First, give your data some *struct*ure. It seems that each 8 byte form a unit of the
form
struct unit {
int key;
int value;
}
If the endianness is right, you can do this in O(1) with a reinterpret_cast. If it isn't, you'll have to live with a O(n) conversion effort. Both vanish compared to the O(n log n) search effort.
When you have an array of these units, you can use std::sort like:
bool compare_units(const unit& a, const unit& b) {
return a.key < b.key;
}
std::sort(array, length, compare_units);
The key to this solution is that you do the "swapping" and byte-interpretation first and then do the sorting.