Algorithm - Make Highest Tower - c++

I've a problem that I could not resolve. I've thought many solutions but no one seems to work.
So that's my problem:
You're given n1, n2, .... nk LEGOs, each one with a even number of faces.
Every LEGO can be stacked up another one only if :
the upper LEGO has the same face of the LEGO under it;
the upper LEGO must have a number of faces that is less or equal to the number of faces of the LEGO under it.
In addition to this every face has an opposite face which is inserted by input after the first one;
example: LEGO1 - face1, face2, face3, face4 (face1 and face2 are opposites such as face3 and face4).
The problem asks to make the highest tower with these LEGOs using each LEGO only once.
The tower must have only 1 direction so it can go only from left to right or from bottom to the top.
Thanks a lot and sorry for my bad English :/
INPUT EXAMPLE:
Lego1 - f1, f2, f3, f4, f5, f6
Lego2- f33, f47, f98, f123
Lego3 - f4,f127
OUTPUT EXAMPLE:
2

Resembles a task I had long ago. Idea of the algorithm was:
put items (legos) in circular list (closed single-linked list);
make function which
in loop
takes next element from the list (deletes it)
recursively cals itself
inserts previously deleted element
advances to the next element
When list gets empty You have got one of possible lego sequences. Algorithm builds all possible seaquences using each list element only once.
Working code:
#include <stdio.h>
#define MAX 4
struct CList{
int d;
struct CList *next;
};
void search(struct CList *pstart);
void result(struct CList *v[MAX], const int nv);
int main(){
static struct CList lst[MAX];
struct CList *p = lst;
int i;
for( i = 0; i < MAX - 1; i++){
lst[i].d = i;
lst[i].next = lst + i + 1;
}
lst[MAX-1].d = MAX - 1;
lst[MAX-1].next = lst;
search( p );
return 0;
}
void search(struct CList *pstart){
struct CList *p, *pp;
static struct CList *v[MAX];
static int nv = 0;
if( pstart->next == pstart ){
v[nv++] = pstart;
result( v, nv );
nv--;
return;
}
nv++;
p = pstart;
do{
pp = p;
p = p->next;
v[nv-1] = p;
pp->next = p->next;
search( pp );
p->next = pp->next;
pp->next = p;
} while( p != pstart );
nv--;
}
void result(struct CList *v[MAX], const int nv){
int i;
for( i = 0; i < nv; i++ ){
printf(" %d ", v[i]->d);
}
puts( "" );
}
In Your case further optimization may be possible (for example breaking the recurson when current element dosn't stack).

Related

C++ permutation tree

I have tasks and I want to calculate the most profitable order to arrange them.
Instead of checking every permutation and doing n*n! calculations, I want to build a tree of permutations, that is, the number of children at each level decreases by 1, and at each node the sub-permutation that has already been calculated will be saved and not recalculated.
For example, if I have 4 tasks, the tree will look like this:
My attached code is missing. I don't know how to build the tree and the give nodes the indexes as in the figure. I know how to deal with a binary tree, but not with a tree where the number of children is different at each lavel.
(The value of each task depends on its location.
I know how to do that, so I didn't include it in the question).
int n = 4;
struct node
{
int task_index = -1;
double value;
struct node **next;
};
void build_tree(node *current_node, int current_level = 0)
{
if (current_level < 1 || current_level >= n)
return;
// current_node->task_index = ? ;
current_node->next = new node *[n - current_level];
for (int i = 0; i < n - current_level; i++)
{
build_tree(current_node->next[i], current_level + 1);
}
}
void print_tree(node *current_node, int current_level = 0)
{
// print indexes
}
void delete_tree(node *current_node, int current_level = 0)
{
// delete nodes
}
int main()
{
struct node *root = new node;
build_tree(root);
print_tree(root);
delete_tree(root);
delete root;
return 0;
}
void build_tree(node *current_node, int current_level = 0)
{
if (current_level < 1 || current_level >= n)
return;
// current_node->task_index = ? ;
current_node->next = new node *[n - current_level];
for (int i = 0; i < n - current_level; i++)
{
build_tree(current_node->next[i], current_level + 1);
}
}
When called with the default parameter of current_level = 0, as you illustrate in your code below, this function exits on the first line without doing anything. You need to decide whether you are indexing starting from 0 or from 1.
Other than that, the general outline of the algorithm looks okay, although I did not explicitly check for correctness.
Now, more broadly: is this an exercise to see if you can write a tree structure, or are you trying to get the job done? In the latter case you probably want to use a prebuilt data structure like that in the boost graph library.
If it's an exercise in building a tree structure, is it specifically an exercise to see if you can write code dealing with raw pointers-to-pointers? If not, you should work with the correct C++ containers for the job. For instance you probably want to store the list of child nodes in a std::vector rather than have a pointer-to-pointer with the only way to tell how many child nodes exist being the depth of the node in the tree. (There may be some use case for such an extremely specialized structure if you are hyper-optimizing something for a very specific reason, but it doesn't look like that's what's going on here.)
From your explanation what you are trying to build is a data structure that reuses sub-trees for common permutations:
012 -> X
210 -> X
such that X is only instantiated once. This, of course, is recursive, seeing as
01 -> Y
10 -> Y
Y2 -> X
If you look at it closely, there are 2^n such subtrees, because any prefix can have any one of the n input tasks used or not. This means you can represent the subtree as an index into an array of size 2^n, with a total footprint O(n*2^n), which improves on the vastly larger >n! tree:
struct Edge {
std::size_t task;
std::size_t sub;
};
struct Node {
std::vector<Edge> successor; // size in [0,n]
};
std::vector<Node> permutations; // size exactly 2^n
This will have this structure:
permutations: 0 1 2 3 4 ...
|-^
|---^
|-------^
|---^
|-^
Where the node at, e.g., location 3 has both task 0 and 1 already used and "points" to all (n-2) subtrees.
Of course, building this is not entirely trivial, but it compressed the search space and allows you re-use results for specific sub-trees.
You can build the table like this:
permutations.resize(1<<n);
for (std::size_t i = 0; i < size(permutations); ++i) {
permutations[i].successor.reserve(n); // maybe better heuristic?
for (std::size_t j = 0; j < n; ++j) {
if (((1<<j) & i) == 0) {
permutations[i].successor.push_back({j,(1<<j)|i});
}
}
}
Here is a live demo for n=4.
The recursive way to generate permutations is if you have n items then all of the permutations of the items are each of the n items concatenated with the permutations of the n-1 remaining items. In code this is easier to do if you pass around the collection of items.
Below I do it with an std::vector<int>. Once using a vector it makes more sense to just follow the "rule of zero" pattern and let the nodes have vectors of children and then not need to dynamically allocate anything manually:
#include <vector>
#include <algorithm>
#include <iostream>
struct node
{
int task_index = -1;
double value;
std::vector<node> next;
};
std::vector<int> remove_item(int item, const std::vector<int>& items) {
std::vector<int> output(items.size() - 1);
std::copy_if(items.begin(), items.end(), output.begin(),
[item](auto v) {return v != item; }
);
return output;
}
void build_tree(node& current_node, const std::vector<int>& tasks)
{
auto n = static_cast<int>(tasks.size());
for (auto curr_task : tasks) {
node child{ curr_task, 0.0, {} };
if (n > 1) {
build_tree(child, remove_item(curr_task, tasks));
}
current_node.next.emplace_back(std::move(child));
}
}
void print_tree(const node& current_node)
{
std::cout << "( " << current_node.task_index << " ";
for (const auto& child : current_node.next) {
print_tree(child);
}
std::cout << " )";
}
int main()
{
node root{ -1, 0.0, {} };
build_tree(root, { 1, 2, 3 });
print_tree(root);
return 0;
}

Tree being replaced by junk values, when printing tree info

So this is a problem I noticed with a small project I'm working on and I can't figure out what's going on, or what to search to fix it, so I wrote this small program to recreate the problem. I haven't worked with c++ in a few years so apologies if this is a really obvious problem.
#include <iostream>
#include <vector>
using namespace std;
class Cell{
int score;
Cell* next_l;
Cell* next_r;
public:
Cell(int s = 0, Cell *r = nullptr, Cell *l = nullptr){
this -> score = s;
this -> next_l = l;
this -> next_r = r;
}
int getScore(){
return this -> score;
}
void disp(){
cout << "Score: " << this -> score << endl; //Problem Line
if(this -> next_r != nullptr){
this -> next_r -> disp();
}
if(this -> next_l != nullptr){
this -> next_l -> disp();
}
}
};
// returns a cell that's the head of a binary tree
// formed by replacing last two cells in the vector
// with a Cell pointing to those two cells instead,
// and then calling this function on that new vector of cells.
Cell make_tree(vector<Cell> &cells){
if(cells.size() == 1){
return cells[0];
}else{
Cell c1 = *(cells.end() - 1);
cells.pop_back();
Cell c2 = *(cells.end() - 1);
cells.pop_back();
Cell cell = Cell(c1.getScore() + c2.getScore(), &c1, &c2);
cells.push_back(cell);
return make_tree(cells);
}
}
int main(){
vector<Cell> cells;
for(int i = 0; i < 3; i++){
Cell *ptr{new Cell(i)};
cells.push_back(*ptr);
}
Cell head = make_tree(cells);
head.disp();
return 0;
}
So the line that I marked as //Problem Line is where I faced confusion while debugging. After printing the score, for some reason, all the values in the tree after a certain depth get replaced by random junk. This eventually leads to a segmentation fault. I have no idea how to proceed with fixing this problem.
The problem is that you are taking pointers to local variables in this line:
Cell cell = Cell(c1.getScore() + c2.getScore(), &c1, &c2);
The members next_l and next_r are pointing to variables c1 and c2 that are on the stack which is not ok. These values are invalid the moment the function terminates and are overwritten when other function calls are made afterward.
Try to change the code so that the cells will be placed in vector<Cell*> cells. Then your code will look like:
Cell* make_tree(vector<Cell*> &cells) {
...
Cell* c1 = *(cells.end() - 1);
cells.pop_back();
Cell* c2 = *(cells.end() - 1);
cells.pop_back();
Cell* cell = new Cell(c1->getScore() + c2->getScore(), c1, c2);
cells.push_back( cell );
return make_tree( cells );
...
}
You will have to delete the resulting cell (delete head;) at the end of the program and you will also have to write a destructor for Cell that will delete its left and right children. You could avoid this by using shared pointers (std::shared_ptr) instead of raw pointers:
std::shared_ptr<Cell> next_l, next_r
vector<std::shared_ptr<Cell>> cells;
std::shared_ptr<Cell> make_tree(vector<std::shared_ptr<Cell>> &cells)
std::shared_ptr<Cell> c1, c2
auto cell = std::make_shared<Cell>(c1->getScore() + c2->getScore(), c1, c2)
Because of std::make_shared you will also need the default constructor:
class Cell{
...
Cell() = default;
...
};

Stuck/general help in developing A* on a 2D grid

I think I am close to finishing this implementation of A* but my mind is becoming fried and am looking for pointers on what I should be doing to complete it.
My current problem is that my function that runs through A* remains stuck on the same node, as in the current node never moves into any other of the open nodes.
Here is my main function, note that the heuristic(Node &n1, Node &n2) function is currently set to always to return 0, so it should currently be working more like a Dijkstra algorithm rather than A*. Also, movement is restricted to the NESW plane, no diagonal movement, so distance_between(Node &n1, Node &n2) always returns 1.
void astar(Node start_, Node end_) {
Node start = start_;
Node end = end_;
// compute f,g,h for the start node
start.g = 0;
start.h = heuristic(start, end);
start.f = start.g + start.h;
// insert start node into the open set
openNodes.insert(&start);
// while the set of open nodes is not empty
while (openNodes.size() > 0) {
// pick the most promising node to look at next
Node currentNode;
cout << "currentNode before: ";
currentNode.displaylocation();
// go through all the open nodes and find the one with the smallest 'f' value
Node* minf = (*openNodes.begin()); // set initial value for minimum f to be the first node in the set of open nodes
for (auto n : openNodes) {
if (n->f <= minf->f) {
minf = n;
}
}
currentNode = *minf; // set the current node to the node that holds the smallest 'f' value
cout << "currentNode after: ";
currentNode.displaylocation();
// if the current node is the end node, then we have found a path
if (currentNode.type == -3) {
break;
}
// remove the current node from the set of open nodes, and add it to the set of closed nodes
openNodes.erase(&currentNode);
closedNodes.insert(&currentNode);
// go through the currents node's neighbours
for (auto n : neighbours(currentNode)) {
cout << "neighbour local: " << n.location.x << "," << n.location.y << "\n";
if (closedNodes.count(&n) == 0 && n.type != -2) { // if this node is neither closed or a blocker
int new_g = currentNode.g + distance_between(currentNode, n);
if (openNodes.count(&n) != 0) { // if we have not seen this node before, add to the open set
openNodes.insert(&n);
}
else if (new_g >= n.g) { // else if we have seen this node before, and already found a shorter path to it from the starting node
}
n.g = new_g;
n.f = n.g + heuristic(n, end);
n.parent_ = &currentNode;
}
}
cout << "\n A* run success! \n";
//break;
}
}
Here is the deceleration of things like the Node struct and the global variables:
// The size of the grid
#define WIDTH 6
#define HEIGHT 6
// Holds values for x and y locations on the grid
struct Coord {
int x, y;
};
// holds data for each node required for A*
struct Node {
int type; // used for defining if this node is a blocker, empty, start or end
Coord location;
int g = 0;
int h = 0;
int f = g + h;
Node *parent_; // pointer to this node's parent
std::string debugmessage;
void displaylocation() {
std::cout << "I am the node at: " << location.x << "," << location.y << "\n";
}
};
// The 2D grid array for A*, requiring a Node struct to store the data of each cell
Node astarArray[WIDTH][HEIGHT];
// Sets for A*
std::set<Node *> openNodes; // contains the nodes that are yet to be considered (if this is empty, then there are no more paths to consider or there is no path)
std::set<Node *> closedNodes; // contains the nodes that have already been considered (if the end node is placed in here, a path has been found)
// stores the start and end values for A*
Node start_A, end_A;
void astar(Node start_, Node end_);
int distance_between(Node& n1, Node& n2);
int heuristic(Node& n1, Node& n2);
std::list<Node> neighbours(Node& n_);
// returns the distance between two nodes for A*
int distance_between(Node& n1, Node& n2) {
return 1; // always return 1 as we are working in a grid restricted to NSEW movement
}
int heuristic(Node& n1, Node& n2) {
return 0; // return 0 to work as a Dijkstra algorithm rather than A*
}
// finds a node's neighbours for A*
std::list<Node> neighbours(Node& n_) {
std::list<Node> neighbours_;
int x = n_.location.x;
int y = n_.location.y;
// start at the location belonging to 'n_'
//for (int y = n_.location.y; y < HEIGHT; y++) {
//for (int x = n_.location.x; x < WIDTH; x++) {
// east
if (x < WIDTH - 1) {
neighbours_.push_back(astarArray[x + 1][y]);
}
// west
if (x > 0) {
neighbours_.push_back(astarArray[x - 1][y]);
}
// south
if (y < HEIGHT - 1) {
neighbours_.push_back(astarArray[x][y + 1]);
}
// north
if (y > 0) {
neighbours_.push_back(astarArray[x][y -1]);
}
//}
//}
return neighbours_;
}
Thank you very much for reading and for any help you can give. I will provide more code if required.
The main problem you have is that you are using the pointers (mem address) to find out if a node is in your set or not.
currentNode = *minf; // set the current node to the node that holds the smallest 'f' value
Then you copy to currentNode the contents of minf.
currentNode will have a different address from the pointer to minf
openNodes.erase(&currentNode); will not remove minf because currentNode does not have the same address.
I would suggest you investigate more on how to implement A* as you are missing some steps. Look for priority queues.
Instead of the mem address of the node, use the position index for that node in the grid (pos.x * numCols) + pos.y

A Problem with Vectors (std::out_of_range)

Here is the description of my problem:
The Program's Description:
I am implementing a program in C++ that tests Prim's algorithm for finding minimum spanning trees. The objective of the program is calculating the number of seconds it takes to find the minimum spanning tree for a selected number of random graphs.
What i have done up to now?
I finished the implementation of the functions and the header files for the whole program. Since the source code is small, i decided for clarity reasons to paste it with this mail in order to provide a better visualization of the problem.
The Problem:
For some reason, i am facing some sort of "out of range" vector problem during the run time of the application.
The problem is marked in the ("Prim_and_Kruskal_Algorithms.cpp") file.
Requesting help:
I would be really grateful if anyone can help me spotting the problem. I have inlined the source code with this question.
The Source Code:
The (Undirected_Graph.h) file:
#ifndef UNDIRECTED_GRAPH_H
#define UNDIRECTED_GRAPH_H
#include <vector>
using std::vector;
#include <climits>
class Edge;
class Node
{
public:
Node(int); //The constructor.
int id; //For the id of the node.
bool visited; //For checking visited nodes.
int distance;
vector <Edge*> adj; //The adjacent nodes.
};
class Edge
{
public:
Edge(Node*, Node*, int); //The constructor.
Node* start_Node; //The start_Node start of the edge.
Node* end_Node; //The end of the edge.
int w; //The weight of the edge.
bool isConnected(Node* node1, Node* node2) //Checks if the nodes are connected.
{
return((node1 == this->start_Node && node2 == this->end_Node) ||
(node1 == this->end_Node && node2 == this->start_Node));
}
};
class Graph
{
public:
Graph(int); //The Constructor.
int max_Nodes; //Maximum Number of allowed Nodes.
vector <Edge*> edges_List; //For storing the edges of the graph.
vector <Node*> nodes_List; //For storing the nodes of the graph.
void insertEdge(int, int, int);
int getNumNodes();
int getNumEdges();
};
#endif
The (Undirected_Graph.cpp) file:
#include "Undirected_Graph.h"
Node::Node(int id_Num)
{
id = id_Num;
visited = 0;
distance = INT_MAX;
}
Edge::Edge(Node* a, Node* b, int weight)
{
start_Node = a;
end_Node = b;
w = weight;
}
Graph::Graph(int size)
{
max_Nodes = size;
for (int i = 1; i <= max_Nodes; ++i)
{
Node* temp = new Node(i);
nodes_List.push_back(temp);
}
}
void Graph::insertEdge(int x, int y, int w)
{
Node* a = nodes_List[x-1];
Node* b = nodes_List[y-1];
Edge* edge1 = new Edge(a, b, w);
Edge* edge2 = new Edge(b, a, w);
edges_List.push_back(edge1);
a->adj.push_back(edge1);
b->adj.push_back(edge2);
}
int Graph::getNumNodes()
{
return max_Nodes;
}
int Graph::getNumEdges()
{
return edges_List.size();
}
The (Prim_and_Kruskal_Algorithms.h) File:
#ifndef PRIM_AND_KRUSKAL_ALGORITHMS_H
#define PRIM_AND_KRUSKAL_ALGORITHMS_H
class PKA
{
private:
//inline void generateRandomGraph();
protected:
//-No Protected Data Members in this Class.
public:
void runAlgorithms();
void prim();
};
#endif
The (Prim_and_Kruskal_Algorithms.cpp) file
*(The problem is in this file and is marked below):*
#include "Prim_and_Kruskal_Algorithms.h"
#include "Undirected_Graph.h"
#include <iostream>
using std::cout;
using std::cin;
using std::endl;
#include <cstdlib>
using std::rand;
using std::srand;
#include <ctime>
using std::time;
//=============================================================================
//============Global Variables and Settings for the program====================
//=============================================================================
const int numIterations = 1; //How many times the Prim function will run.
const int numNodes = 10; //The number of nodes in each graph.
const int numEdges = 9; //The number of edges for each graph.
const int sRandWeight = 1; //The "start" range of the weight of each edge in the graph.
const int eRandWeight = 100; //The "end" range of the weight of each edge in the graph.
//=============================================================================
//=============================================================================
//=============================================================================
void PKA::runAlgorithms() //Runs the Algorithms
{
srand( time(0) );
cout << "------------------------------" << endl;
//Calling the Functions:
cout << "\nRunning the Prim's Algorithms:\nPlease wait till the completion of the execution time" << endl;
//===============================================
//Start the clock for Prim's Algorithm:
clock_t start, finish;
start = clock();
for(int iter1 = 1; iter1 <= numIterations; ++iter1)
{
prim();
}
//Stop the clock for Prim and print the results:
finish = clock();
cout << "\n\tThe execution time of Prim's Algorithm:\t" << ((double)(finish - start) / CLOCKS_PER_SEC) << " s";
return;
}
void PKA::prim()
{
//=============================================================================
//=============================Generating A Random Graph=======================
//=============================================================================
//Randomizing Values:
//===============================================
int randStartNode = rand() % numNodes; //Generation a random start node.
int randEndNode = rand() % numNodes; //Generating a random end node.
int randWeight; //Random weight for the edge.
while(randEndNode == randStartNode) //Checking if both randomized nodes are equal.
{
randEndNode = (rand() % numNodes);
}
//===============================================
Graph myGraph(numNodes);
for(int i = 0; i < numEdges; ++i)
{
//Generating a random weight:
randWeight = sRandWeight + rand() % eRandWeight;
//Inserting a new Edge:
myGraph.insertEdge(randStartNode, randEndNode, randWeight);
}
//=============================================================================
//=============================================================================
//=============================================================================
int currentNode = 0; //The current Node being under investigation.
int adjCounter = NULL; //How many adjacent nodes do we have for the current node.
int minDistance = NULL;
int minIndex = 0;
myGraph.nodes_List[0]->distance = 0; //Indicate the start node.
myGraph.nodes_List[0]->visited = 1; //The starting node is already considered as a visited node.
for(int i = 0; i < numNodes - 1; i++)
{
//Determine how many adjacent nodes there are for the current node:
adjCounter = myGraph.nodes_List[currentNode]->adj.size();
if(adjCounter == 0) //If there are no adjacent nodes to the current node:
{
myGraph.nodes_List[currentNode]->adj.at(minIndex)->end_Node->visited = 1;
cout << "\n*******Not all nodes are connected!*******" << endl;
continue;
}
minDistance = myGraph.nodes_List[currentNode]->adj.at(0)->w;
minIndex = 0;
for(int counter = 0; adjCounter > 0; adjCounter--, counter++)
{
if(myGraph.nodes_List[currentNode]->adj[counter]->end_Node->visited == false)
{
if(myGraph.nodes_List[currentNode]->distance > myGraph.nodes_List[currentNode]->adj[counter]->w)
{
myGraph.nodes_List[currentNode]->distance = myGraph.nodes_List[currentNode]->adj[counter]->w;
}
if(minDistance > myGraph.nodes_List[currentNode]->adj[counter]->w)
{
minDistance = myGraph.nodes_List[currentNode]->adj[counter]->w;
minIndex = counter;
}
}
}
//======================================================================================
//=========================The Problem is in the following two lines====================
//======================================================================================
//Mark the current node as visited:
myGraph.nodes_List[currentNode]->adj.at(minIndex)->end_Node->visited = 1;
//Switching to the next node that we have just visited:
currentNode = myGraph.nodes_List[currentNode]->adj.at(minIndex)->start_Node->id;
//======================================================================================
//======================================================================================
//======================================================================================
}
}
The (Client_Code.cpp) file: For testing the program.
#include "Prim_and_Kruskal_Algorithms.h"
#include <iostream>
using std::cout;
using std::endl;
int main()
{
cout << "\nWelcome to the Prim and Kruskal Algorithms Comparison!" << endl;
cout << "\nPlease wait until the completion of the algorithms." << endl;
PKA myPKA; //Creating an object of the class.
myPKA.runAlgorithms(); //Running the Algorithm.
cout << "\n\nThe program terminated successfully!" << endl;
return 0;
}
Look at this line:
myGraph.nodes_List[currentNode]->adj.at(minIndex)->end_Node->visited = 1;
As an experienced C++ programmer, I find that line terrifying.
The immediate cause of trouble is that adj doesn't have as many members as you think it does; you're asking for (in my test run) the 5th element of a list of size zero. That sends you off the map, where you then start manipulating memory.
More generally, you are not checking bounds.
More generally still, you should allow these classes to manage their own members. Use accessors and mutators (getX() and setX(...)) so that member access happens all in one place and you can put the bounds checking there. Reaching down myGraph's throat like that is very unsafe.
You'll notice that I haven't said where/when/how the program diverges from intention so that the list doesn't have as many elements as it should. That's because it's too much trouble for me to track it down. If you organize the classes as I suggest, the code will be a lot cleaner, you can check your assumptions in various places, and the bug should become obvious.
EDIT:
To create a random connected graph, try this:
Graph myGraph(numNodes); //Create a new Graph.
// This ensures that the kth node is connected to the [1...(k-1)] subgraph.
for(int k=2 ; k<=numNodes ; ++k)
{
randWeight = rand() % eRandWeight;
myGraph.insertEdge(k, rand()%(k-1)+1, randWeight);
}
// This adds as many extra links as you want.
for(int i = 0; i < numExtraEdges; ++i)
{
randWeight = rand() % eRandWeight;
randStartNode = rand()%(numNodes-1)+1;
randEndNode = rand()%(numNodes-1)+1;
myGraph.insertEdge(randStartNode, randEndNode, randWeight);
}
You have too much code for a casual examination to be sure of anything. But the .at() method will throw the out-of-range exception that you mentioned and that crashing line occurs right after you've updated minIndex so I would suggest reviewing the code that determines that value. Are you using a debugger? What is the value of minIndex at the point of the exception and what is the allowable range?
Also, when you have a monster line of compounded statements like that, it can help in debugging problems like this and give you clearer, simpler looking code if you break it up. Rather than repeating big chunks of code over and over, you can have something like this:
Node * node = myGraph.nodes_List[currentNode];
assert(node);
Edge * minAdjEdge = node->adj.at(minIndex);
assert(minAdjEdge);
Then use minAdjEdge to refer to that edge instead of that repeated compound statement.
It also seems odd to me that your first use of minIndex in the big loop is still using the value determined from the node in the previous iteration, but it's applying it to the new current node. Then you reset it to zero after possibly using the stale value. But that isn't near the line that you say is causing the crash, so that may not be your problem. Like I said, you have a lot of code pasted here so it's hard to follow the entire thing.
It is too much code, but what I can observe at the first glance is that for some reason you are mixing 0-based and 1-based iteration.
Is this intentional? Couldn't that be the cause of your problem?

Iterative version of a recursive algorithm is slower

I'm trying to implement an iterative version of Tarjan's strongly connected components (SCCs), reproduced here for your convenience (source: http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm).
Input: Graph G = (V, E)
index = 0 // DFS node number counter
S = empty // An empty stack of nodes
forall v in V do
if (v.index is undefined) // Start a DFS at each node
tarjan(v) // we haven't visited yet
procedure tarjan(v)
v.index = index // Set the depth index for v
v.lowlink = index
index = index + 1
S.push(v) // Push v on the stack
forall (v, v') in E do // Consider successors of v
if (v'.index is undefined) // Was successor v' visited?
tarjan(v') // Recurse
v.lowlink = min(v.lowlink, v'.lowlink)
else if (v' is in S) // Was successor v' in stack S?
v.lowlink = min(v.lowlink, v'.lowlink )
if (v.lowlink == v.index) // Is v the root of an SCC?
print "SCC:"
repeat
v' = S.pop
print v'
until (v' == v)
My iterative version uses the following Node struct.
struct Node {
int id; //Signed int up to 2^31 - 1 = 2,147,483,647
int index;
int lowlink;
Node *caller; //If you were looking at the recursive version, this is the node before the recursive call
unsigned int vindex; //Equivalent to the iterator in the for-loop in tarjan
vector<Node *> *nodeVector; //Vector of adjacent Nodes
};
Here's what I did for the iterative version:
void Graph::runTarjan(int out[]) { //You can ignore out. It's a 5-element array that keeps track of the largest 5 SCCs
int index = 0;
tarStack = new stack<Node *>();
onStack = new bool[numNodes];
for (int n = 0; n < numNodes; n++) {
if (nodes[n].index == unvisited) {
tarjan_iter(&nodes[n], index);
}
}
}
void Graph::tarjan_iter(Node *u, int &index) {
u->index = index;
u->lowlink = index;
index++;
u->vindex = 0;
tarStack->push(u);
u->caller = NULL; //Equivalent to the node from which the recursive call would spawn.
onStack[u->id - 1] = true;
Node *last = u;
while(true) {
if(last->vindex < last->nodeVector->size()) { //Equivalent to the check in the for-loop in the recursive version
Node *w = (*(last->nodeVector))[last->vindex];
last->vindex++; //Equivalent to incrementing the iterator in the for-loop in the recursive version
if(w->index == unvisited) {
w->caller = last;
w->vindex = 0;
w->index = index;
w->lowlink = index;
index++;
tarStack->push(w);
onStack[w->id - 1] = true;
last = w;
} else if(onStack[w->id - 1] == true) {
last->lowlink = min(last->lowlink, w->index);
}
} else { //Equivalent to the nodeSet iterator pointing to end()
if(last->lowlink == last->index) {
numScc++;
Node *top = tarStack->top();
tarStack->pop();
onStack[top->id - 1] = false;
int size = 1;
while(top->id != last->id) {
top = tarStack->top();
tarStack->pop();
onStack[top->id - 1] = false;
size++;
}
insertNewSCC(size); //Ranks the size among array of 5 elements
}
Node *newLast = last->caller; //Go up one recursive call
if(newLast != NULL) {
newLast->lowlink = min(newLast->lowlink, last->lowlink);
last = newLast;
} else { //We've seen all the nodes
break;
}
}
}
}
My iterative version runs and gives me the same output as the recursive version. The problem is that the iterative version is slower, and I'm not sure why. Can anyone give me some insight on my implementation? Is there a better way to implement the recursive algorithm iteratively?
A recursive algorithm uses the stack as storage area. In the iterative version, you use some vectors, which themselves rely on heap allocation. Stack-based allocation is known to be very fast, since it is only a matter of moving an end-of-stack pointer, whereas heap allocation may be substantially slower. That the iterative version is slower is not fully surprising.
Generally speaking, if the problem at hand fits well within a stack-only recursive model, then, by all means, recurse.