which is faster method to traverse an array - c++

Compare following two codes:
for (int i = 0; i<array_size; i++)
cout << array[i] << endl;
OR
int* p_end = array+array_size;
for (int* p_array = array; p_array != p_end; p_array++)
cout << *p_array << endl;
Which one is faster?
Another question is if we just want to traverse then which is faster: link list or array? Thankyou!

array[i] is potentially faster because the compiler knows you're not aliasing your pointer to someplace you really shouldn't.
Lists are much slower to traverse because of indirection imposed inbetween every node - this will ruin your caches and cause many a cache miss, which is probably the worst thing that can happen to a modern processor.

The first one is likely to be faster on an array.
The second one terminates on finding a zero entry in the structure. It really isn't the same thing. But suppose you changed your code to read:
p_array = array;
for (int i = 0; i < array_size; ++i, ++p_array)
cout << *p_array << endl;
That loop would probably take the same amount of time as the first one with any modern compiler. (In all actuality, the cost of cout would swamp everything anyway.)
The best approach for iterating through a container is really dictated by the container. vector<T> allows O(1) random access via operator[]. Also, its iterators offer O(1) operator++. In contrast, a container like list<T> only lets you use operator++, and it's O(1).
And final thought: You likely want to stick to pre-increment instead of post-increment in C++ when you can.

Note the following:
for (int i = 0; i<array_size; i++)
cout << array[i] << endl;
Each loop you must - compare i to array size, increment i, add i to array
int* p_end = array+array_size;
for (int* p_array = array; p_array != p_end; p_array++)
cout << *p_array << endl;
Each loop you must - compare p_array to p_end, increment p_array (there is no add here)
So it would seem that the second loop - becuase it does not have to do an add should be faster
However - optimizers can do quite a lot so I would recommend compiling both and then comparing the asm for each loop
Also for your second question - Arrays are faster than linked lists to traverse because of the load time for each node and because they take more memory so fewer nodes can be cached

Related

C++ Removing empty elements from array

I only want to add a[i] into the result array if the condition is met, but this method causes empty elements in the array as it adds to result[i]. Is there a better way to do this?
for(int i=0; i<N; i++)
{
if(a[i]>=lower && a[i]<=upper)
{
count++;
result[i]=a[i];
}
}
you can let result stay empty at first, and only push_back a[i] when the condition is met:
std::vector<...> result;
for (int i = 0; i < N; i++)
{
if (a[i] >= lower && a[i] <= upper)
{
result.push_back(a[i]);
}
}
and count you can leave out, as result.size() will tell you how many elements satisfied the condition.
to get a more modern solution, like how Some programmer dude suggested, you can use std::copy_if in combination with std::back_inserter to achieve the same thing:
std::vector<...> result;
std::copy_if(a.begin(), a.end(), std::back_inserter(result),
[&](auto n) {
return n >= lower && n <= upper;
});
Arrays in c++ are dumb.
They are just pointers to the beginning of the array and don't know their length.
If you just arr[i] you have to be sure that you aren't out of bounds. In that case it is undefined behavior as you dont know what part of meory have you written over. You could as well write over a different variable or beginning of another array.
So when you try to add results to an array you already have to have the array created with enough space.
This boilerplate of deleting and creating dumb arrays so that you can grow the array is very efficiently done in std::vector container which remembers number of elements stored, number of elements that could be stored and the array itself. Every time you try to add element when the reserved space is full it creates a new array two times the size of the original one and copy the data over. Which is O(n) in worst case but O(1) in avarege case (it may deviate when the n is under certain threshold)
Then the answer from Stack Danny applies.
Also use emplace_back instead of push_back if you can it is able to construct the data type in place based on the constructor parameters and in other cases it tries to act like push_back. It basically does what you want the fastest way possible so you avoid as much copies as possible.
count=0;
for(int i=0; i<N; i++)
{
if(a[i]>=lower && a[i]<=upper)
{
count++;
result[count] = a[i];
}
}
Try this.
Your code was copying elements from a[i] and pasting it in result[i] at random places.
For example, if a[0] and a[2] meet the required condition, but a[1] doesn't, then your code will do the following:
result[0] = a[0];
result[2] = a[2];
Notice how result[1] remains empty because a[1] didn't meet the required condition. To avoid empty positions in the result array, use another variable for copying instead of i.

Cout a whole array in c++

I am fairly new to c++, is there a way in c++ through which we can cout a whole static array apart from iterating via a for loop?
int arra[10] = {1,2,3,4};
std::cout << arra << std::endl;
I tried this but, this is printing address of the first element in the array.
Following doesn't use (explicitly) loop:
std::copy(std::begin(arra),
std::end(arra),
std::ostream_iterator<int>(std::cout, "\n"));
but loop seems simpler to read/write/understand:
for (const auto& e : arra) {
std::cout << e << std::endl;
}
#include<iostream>
using namespace std;
int main(){
int i;
int myarr[5]={9,84,7,55,6};
for(i=0;i<5;i++){
cout<<myarr[i]<<endl;
}
}
Some how you are going to have to visit each element of the array to display the contents. This can be done long form or use a loop. Fortunately we can use std::copy to fide the loop and display the array.
int arr[] = {1,2,3,4,5};
std::copy(std::begin(arr), std::end(arr), std::ostream_iterator<int>(std::cout, " "));
Live Example
You need to either loop over the array
int arra[10] = {1,2,3,4};
for (int i = 0; i<sizeof(arra)/sizeof(arra[0]); ++i)
{
std::cout << arra[i] << std::endl;
}
or use
std::copy(std::begin(arra), std::end(arra), std::ostream_iterator<int>(std::cout,"\n"));
As you asked to do this without an Array, you could easily do this:
std::copy(arra, arra + 10,
std::ostream_iterator<int>(cout, "\n"));
If you want to write good code, you could use std::array and then simply write arra.begin() and arra.end().
There are basically two ways. First one is a loop somewhere . The loop can be explicit - in your code - or it can be implicit through library. Example of library loop:
std::for_each(cbegin(arra), cend(arra), [](int i) {std::cout << "i ";});
The second way of printing the array is with the use of recursion. Here is example of the code:
void print_element(const int* head, const int* tail) {
if (head == tail)
return;
std::cout << *head << " ";
print_element(head + 1, tail);
}
....
print_element(arr, arr + sizeof(arr) / sizeof(*arr));
Couple of words about recursion solution. Depending on your optimization, it can produce different results. Performance of the recursion will be roughly equivalent to the performance of the loop on any optimization level with AMD64 ABI. The reason for that is that arguments to functions are passed through registers (not pushed into stack), and the frame pointers are not used with any optimization. With this in mind, the only CALL/RET (which push/pop RIP) will slow down execution compared the loop, but this degradation is not measurable. The real issue, however, is that there is limited number of recursed calls which can be made on a given system (usually around single thousands), so printing an array of 1000000 elements is guaranteed to crash the application.
With higher levels of optimization which involve tail-call optimization, the recursion calls will be translated into plain jmps and the performance will be exactly the same as one with the loop. It will also eliminate the problem of maximum recursion level - so that arrays of any sizes can be printed.
It is printing address because you are pointing to an array, not its elements.
try this-
void printArray(int arr[], int n)
/* n is size here*/
{
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
}

Is this legal use of a for loop?

For instance:
vector<int> something;
//imagine i add some elements to the vector here
int* pointy;
for (int i = 0; i < something.size(); pointy = &something[i++]) {
//do some work with pointy
}
it seems to work and saves me a line but is there any danger of weird bugs popping up down the line because of this?
This may not be legal, because pointy is unassigned on the first iteration. If the loop does not dereference pointy during the initial iteration, it may be OK, but it is not possible to tell without seeing the body of the loop.
Since you are using std::vector, using iterators would save you another line, because you wouldn't need to declare pointy. You would be able to determine the offset without i by subtracting something.begin() from the current iterator:
for (vector<int>::iterator iter = something.begin() ; iter != something.end() ; ++iter) {
cout << "Item at index " << (iter - something.begin()) << " is " << *iter << endl;
}
Yes, that is dangerous, as dasblinkenlight pointed out. But there's a simpler way to eliminate this kind of problems.
Write your code for simplicity and readability first. Compressing your loop into the smallest possible number of lines won't add anything in terms of performance, and even if it did, you shouldn't care as long as your profiler doesn't tell you that your loop is a bottleneck.
On the other hand, it will make your code harder to read and, possibly, more prone to bugs (as you've probably noticed).
In C++11, consider using a range-based for loop:
for (int& p : something)
{
// ...
}
In C++03, consider using std::for_each(), or a classical loop based on iterators:
for (std::vector<int>::iterator i = something.begin(); i != something.end(); ++i)
{
// use *i to refer to the current pointy
// use (i - something.begin()) to get its index
// ...
}
It is very dangerous, because i is not unsigned. It can blow up in some rare cases. :)
Is this safe really depends on what you are after.
pointy is going to be a pointer to an element in the vector.
This means that if you change the value of pointy, or what it points to be more specific, you are actually changing the content of the vector for that specific element.
As for me, I like to handle std::vector like this for larger Objects:
std::vector<int*> mynumbers;
//add elements here like this:
int somenumber = 5;
mynumbers.push_back(&somenumber);
for(int i=0;i<elemnts.size();i++)
{
cout << "Element Nr. " << i << ": " << *elements.at(i) << endl;
//modify like this:
*elements.at(i) = 0;
}
The pointer instead of the variable itself is because std::vector handles pointers faster than large objects itself, but for int, this doesn't really make much difference so you can also do it like this:
std::vector<int> mynumbers;
mynumbers.push_back(5);
int* pointy
for(int i=0;i<elemnts.size();i++)
{
pointy = &elements.at(i);
}
Works great for me!

Why can't I insert 6 million elements in STL set?

I am trying to insert a little over 6.5 million elements(ints) in an stl set. Here is the code:
set<int> s;
cout << s.max_size() << endl;
for(int i = 0; i < T.MULT * T.MAXP; i++) {
s.insert(a[i]);
}
T.MULT is 10; T.MAXP is 666013.
a is an array - statically allocated - (int a[T.MULT * T.MAXP];) that contains distinct elements.
After about 4.6 million elements s.insert() throws a bad_alloc exception. The resource monitor available on Windows 7 says I have 3 GB free memory left.
What am I doing wrong? Why can't STL set allocate the memory?
Edit: Here is the full code: http://ideone.com/rdrEnt
Edit2: apparently the inserted elements might not be distinct after all, but that should not be a problem.
Edit3: Here is a simplified version of the code: http://ideone.com/dTp0fZ
The problem actually lies in the fact that you statically allocated the array A with more than 6.5 million elements, which corrupts your program stack space. If you allocate the array on the heap, it actually works. I did some code change based on your description, it worked fine.
int *A = new int[T.MULT * T.MAXP];
for (int i= 0; i < T.MULT * T.MAXP; ++i)
{
A[i] = i; //for simplicity purpose, your array may have different elem. values
}
set<int> s;
for (int i = 0; i < T.MULT * T.MAXP; ++i )
{
s.insert(A[i]);
}
cout << s.size();
set<int>::iterator iter;
int count = 0;
for (iter = s.begin(); iter != s.end(); ++ iter)
{
cout << *iter << " ";
count ++;
if (count == 100)
{
cout <<endl;
count = 0;
}
}
delete [] A;
return 0;
It worked perfectly fine with both vector and set. It can print all those 6.6 million elements on the screen.
As other posts indicated, you may also want to try STXXL if you have interest.
You might want to take a look at STXXL.
While I can't answer your question directly, I think it is more efficient to store your data in a std::vector, sort it, and then use std::binary_search to test for the existence of the item. Storage in a std::set is relatively expensive compared to that of std::vector. That's because there is some overhead when storing each element.
As an example, here's how you could do it. This sorts the static array.
std::sort(a,a+(T.MULT*T.MAXP));
bool existence=std::binary_search(a,a+(T.MULT*T.MAXP),3);
Fast and easy.

g++ compiler optimization

list<mpz_class> baseFactor;
1)
int *tab = new int [baseFactor.size()]; //baseFactor.size() ~= 20000
for(i = 0; i < baseFactor.size(); i++){
cout << tab[i] << endl;
}
// Total time: 2.620790
2)
int size = baseFactor.size();
int *tab = new int [size]; //baseFactor.size() ~= 20000
for(i = 0; i < size; i++){
cout << tab[i] << endl;
}
//Total time: 0.366500
Why the g++ compiler doesn't optimize code 1) in 2) ?
Depending on where baseFactor is defined (global variable?), it can be difficult for the compiler to prove that size() always returns the same value.
If it cannot prove that, the call can not be moved out of the loop.
For the first one to be optimised to the 2nd it would requre that baseFactor.size() never changes during the loop.
Of course it probably doesn't, but does the compiler know that?
A std::list container is a linked list, and computing its size may be costly (O(n) algorithm, that has changed in the latest C++11 standard IIRC). The compiler has no idea that the body of your function is not changing basefactor, so its size is computed once in every loop in the first case (at every test of the for loop) and only once in the second.
Maybe you should consider using std::vector instead.