fastest way to traverse a tree structure in cpp with a stack - c++

I've got a tree structure and a running example of how to iterate over it but as I'm a beginner when it comes to performance in coding, I wanted to ask if somebody knows a way to make it faster.
Eigen3 is used to build vectors.
The struct:
struct linkedBoxes{
std::vector<Vector3r> points;
std::vector<linkedBoxes*> boxes;
int sideLength;
};
And the algorithm:
std::vector<Vector3r> integPoints;
std::vector<linkedBoxes*> stack;
stack.push_back(firstBox);
vector<linkedBoxes*>::iterator iterator = stack.begin();
while (iterator != stack.end()){
if((*iterator)->boxes.size() == 0){
for (int j = 0; j < (*iterator)->points.size(); ++j) {
integPoints.push_back(point + (*iterator)->points[j]);
}
} else {
for (int k = 0; k < (*iterator)->points.size(); ++k) {
Vector3r tmpPoint = point + (*iterator)->points[k];
if(computeDistance(tmpPoint) < 0){
const size_t diff = iterator - stack.begin();
stack.push_back((*iterator)->boxes[k]);
iterator = stack.begin() + diff;
}
}
}
++iterator;
}
Point is a vector which is given to the function and computeDistance returns a value between -1 and 1.
Does somebody knows a way to make this faster?
Bruno

Related

Problems with vectors, how to remove the arrays in my vectors?

I have created a function that creates all the possible solutions for a game that I am creating... Maybe some of you know the bullcow game.
First I created a function that creates a combination of numbers of max four integers and the combination can't have any repeating number in it... like...
'1234' is a solution but not '1223' because the '2' is repeating in the number. In total there is 5040 numbers between '0123' and '9999' that haven't repeating numbers.
Here is my function:
std::vector <std::array<unsigned, 4>> HittaAllaLosningar(){
std::vector <std::array<unsigned, 4>> Losningar;
for (unsigned i = 0; i < 10; i++) {
for (unsigned j = 0; j < 10; j++) {
for (unsigned k = 0; k < 10; k++) {
for (unsigned l = 0; l < 10; l++) {
if (i != j && i != k && i != l && j != k && j != l && k != l) {
Losningar.push_back({i,j,k,l});
}
}
}
}
}
return Losningar;
}
Now let's say I have the number '1234' and that is not the solution I am trying to find, I want to remove the solution '1234' from the array since that isn't a solution... how do I do that? have been trying to find for hours and can't find it. I have tried vector.erase but I get errors about unsigned and stuff... also its worth to mention the guesses are in strings.
What I am trying to do is, to take a string that I get from my program and if it isn't a solution I want to remove it from the vector if it exists in the vector.
Here is the code that creates the guess:
std::string Gissning(){
int random = RandomGen();
int a = 0;
int b = 0;
int c = 0;
int d = 0;
for (unsigned i = random-1; i < random; i++) {
for (unsigned j = 0; j < 4; j++) {
if (j == 0) {
a = v[i][j];
}
if (j == 1) {
b = v[i][j];
}
if (j == 2) {
c = v[i][j];
}
if (j == 3) {
d = v[i][j];
}
}
std::cout << std::endl;
AntalTry++;
}
std::ostringstream test;
test << a << b << c << d;
funka = test.str();
return funka;
}
The randomgen function is just a function so I can get a random number and then I go in the loop so I can take the element of the vector and then I get the integers of the array.
Thank you very much for taking your time to help me, I am very grateful!
You need to find the position of the element to erase.
std::array<unsigned, 4> needle{1, 2, 3, 4};
auto it = std::find(Losningar.begin(), Losningar.end(), needle);
if (it != Losningar.end()) { Losningar.erase(it); }
If you want to remove all the values that match, or you don't like checking against end, you can use std::remove and the two iterator overload of erase. This is known as the "erase-remove" idiom.
std::array<unsigned, 4> needle{1, 2, 3, 4};
Losningar.erase(std::remove(Losningar.begin(), Losningar.end(), needle), Losningar.end());
To erase from a vector you just need to use erase and give it an iterator, like so:
std::vector<std::array<unsigned, 4>> vec;
vec.push_back({1,2,3,4});
vec.push_back({4,3,2,1});
auto it = vec.begin(); //Get an iterator to first elements
it++; //Increment iterator, it now points at second element
it = vec.erase(it); // This erases the {4,3,2,1} array
After you erase the element, it is invalid because the element it was pointing to has been deleted. Ti continue to use the iterator you can take the return value from the erase function, a valid iterator to the next element after the one erased, in this the case end iterator.
It is however not very efficient to remove elements in the middle of a vector, due to how it works internally. If it's not important in what order the different solution are stored, a small trick can simplify and make your code faster. Let's say we have this.
std::vector<std::array<unsigned, 4>> vec;
vec.push_back({1,2,3,4});
vec.push_back({4,3,2,1});
vec.push_back({3,2,1,4});
To remove the middle one we then do
vec[1] = vec.back(); // Replace the value we want to delete
// with the value in the last element of the vector.
vec.pop_back(); //Remove the last element
This is quite simple if you have ready other functions:
using TestNumber = std::array<unsigned, 4>;
struct TestResult {
int bulls;
int cows;
}
// function which is used to calculate bulls and cows for given secred and guess
TestResult TestSecretGuess(const TestNumber& secret,
const TestNumber& guess)
{
// do it your self
… … …
return result;
}
void RemoveNotMatchingSolutions(const TestNumber& guess, TestResult result)
{
auto iter =
std::remove_if(possibleSolutions.begin(),
possibleSolutions.end(),
[&guess, result](const TestNumber& possibility)
{
return result == TestSecretGuess(possibility, guess);
});
possibleSolutions.erase(iter, possibleSolutions.end());
}
Disclaimer: it is possible to improve performance (you do not care about order of elements).

Dijkstra algorithm with Adjacency list Undirected Graph

I'm trying to write a method that would find the shortest path length from one vertex to another, using Dijkstra algorithm. But it doesn't give a correct output. Could you give some advice as to where the problem is?
unsigned distDIJKSTRA(unsigned vert1, unsigned vert2)
{
vector<Vertex3*> pq;
Vertex3* v;
unsigned distance = UINT_MAX;
for (unsigned i = 0; i < vertices.size(); i++)
{
if (vertices[i]->value == vert1)
v = new Vertex3(vertices[i], 0);
else
v = new Vertex3(vertices[i], distance);
pq.push_back(v);
}
make_heap(pq.begin(), pq.end(), lowerPrior);
unsigned newDist;
while (!pq.empty())
{
Vertex3* currV = pq.front();
// If the destination is reached
if (currV->vert->value == vert2)
return currV->dist;
pop_heap(pq.begin(), pq.end(), lowerPrior);
pq.pop_back();
// Checking if the route through currV is shorter
for (unsigned i = 0; i < currV->vert->adjList.size(); i++)
{
Vertex3* nextV = nullptr;
for (unsigned j = 0; j < pq.size(); j++)
if (pq[j]->vert == currV->vert->adjList[i]) {
nextV = pq[j];
break;
}
if (nextV != nullptr)
{
newDist = currV->dist + getWeight(currV->vert, nextV->vert);
if (newDist < nextV->dist)
nextV->dist = newDist;
}
else
continue;
}
sort_heap(pq.begin(), pq.end(), lowerPrior);
}
return UINT_MAX;
}
After updating the distances, your vector won't be a heap anymore. Further more, calling sort_heap in itself would also drop the heap property, instead of fixing it. (See http://en.cppreference.com/w/cpp/algorithm/sort_heap)
Call make_heap instead.
Also note the memory leak: you never deallocate the memory allocated for the Vertex3 objects.

How to compute the complement of given vector Indices?

I have a 3D point vector, represented by class Point3D,
std::vector<Point3D> points;
I also have a size_t vector containing indices of the points vector,
std::vector<size_t> indices_true;
Now I want to build the inverse of indices_true, i.e. I want to build another index vector indices_false that contains all indices which are missing in indices_true. How can this be done in a faster way than the following:
for (size_t i = 0; i < points.size(); i++)
{
// TODO: The performance of the following is awful
if (std::find(indices_true.begin(), indices_true.end(), i) == indices_true.end())
indices_false.push_back(i);
}
Needs extra memory, but yields a linear algorithm:
Here is an attempt (neither compiled, nor tested):
indices_false.reserve(points.size() - indices_true.size());
std::vector<char> isTrue(points.size(), false); // avoided std::vector<bool> intentionally
for (const size_t i : indices_true)
{
isTrue[i] = true;
}
for (size_t i = 0; i < points.size(); ++i)
{
if (!isTrue[i])
indices_false.push_back(i);
}
Sort your indices_true vector first and use std::binary_search. To keep the orders within vector using std::stable_sort.
std::stable_sort(indices_true.begin(), indices_true.end());
for (size_t i = 0; i < points.size(); i++)
{
if (std::binary_search(indices_true.begin(), indices_true.end(), i))
indices_false.push_back(i);
}
Sort indices_true and gradually increase an index k within this sorted vector. Increase it when necessary. This yields (beside the initial sorting) a linear algorithm.
Here is an attempt (neither compiled, nor tested):
std::sort(begin(indices_true), end(indices_true));
indices_false.reserve(points.size() - indices_true.size());
size_t k = 0;
for (size_t i = 0; i < points.size(); ++i)
{
if (k < indices_true.size() && i > indices_true[k])
++k;
assert(k >= indices_true.size() || i <= indices_true[k]);
if (k >= indices_true.size() || i != indices_true[k])
indices_false.push_back(i);
}
}

Checking for any collisions between rectangles in a collection

I'm trying to create a C++ function which controls if N rectangles are collisioning. The N rectangles are in a std::vector. The idea is to compare every element of the vector with others (only one time) to verify if there are collisions.
I already implemented code to do this, but I am looking for a better, cleaner and more elegant way (I'm a C++ newbie).
My code is:
bool areCollisioningNRectangles(std::vector<Rectangle> rect) {
const unsigned long size = rect.size();
for (int i = 0; i < size - 1; i++) {
for (int j = i + 1; j < size; j++) {
if (areCollisioningTwoRectangles(rect[i], rect[j])) {
return true;
}
}
}
return false;
}

In place randomized selection algorithm

We are currently studying algorithms hence I marked this question as “homework” even though this is not a homework related task. Just to be safe.
We just studied the randomized selection algorithm, and the logic seems simple. Choose an element from a list, and then put the element in its right place. Then repeat the process in one sub list until the element at the index is in its place. Where index is the position of the element you want in the sort list.
This should be a modified version of the quick sort algorithm. But we only sort one sub list, not both sub lists. Hence a performance boost (in big-oh).
I can successfully implement this algorithm using external storage (C++, and zero based array’s):
int r_select2(vector<int>& list, int i)
{
int p = list[0];
vector<int> left, right;
for (int k = 1; k < list.size(); ++k)
{
if (list[k] < p) left.push_back(list[k]);
else right.push_back(list[k]);
}
int j = left.size();
if (j > i) p = r_select2(left, i);
else if (j < i) p = r_select2(right, i - j - 1);
return p;
}
However, I want to implement the algorithm using in-situ (in-place), and not use extra sub arrays. I believe that this should be an easy/trivial task. But somewhere, my in-situ version goes wrong. Maybe it’s just late and I need to sleep, but I can’t see the root cause of why the following version fails:
int r_select(vector<int>& list, int begin, int end, int i)
{
i = i + begin;
int p = list[begin];
if (begin < end)
{
int j = begin;
for (int k = begin + 1; k < end; ++k)
{
if (list[k] < p)
{
++j;
swap(list[j], list[k]);
}
}
swap(list[begin], list[j]);
if (j > i) p = r_select(list, begin, j, i);
else if (j < i) p = r_select(list, j + 1, end, i - j);
}
return p;
}
In both examples, the first element is being used as the pivot to keep the design simple. In both example, i is the index of the element I want.
Any ideas where the 2nd example is failing? Is it a simple off-by-one error?
Thank you all!
This sounds fishy:
i = i + begin;
...
r_select(list, begin, j, i);