C/C++ qsort an array of struct within a struct - c++

I'm working on Kruskal's algorithm. The sorting part using the qsort function creates a strange behaviour of nodes: It order correctly by weight but changes every node's parent. This behaviour got me a stack overflow when the programs executes the FIND-SET(X) function.
Here is my code:
#include <iostream>
/*
*DISJOINT
*SETS
*/
typedef struct NODE {
int rank;
int data;
struct NODE *parent;
} NODE;
//MAKE-SET(x)
void makeSet(NODE *node) {
node->parent = node;
node->rank = 0;
}
//FIND-SET(x)
NODE *findSet(NODE *node) {
if (node != node->parent) {
node->parent = findSet(node->parent);
}
return node->parent;
}
//LINK(x, y)
void link(NODE *nodeX, NODE *nodeY) {
if (nodeX->rank > nodeY->rank) {
nodeY->parent = nodeX;
} else {
nodeX->parent = nodeY;
if (nodeX->rank == nodeY->rank) {
nodeY->rank += 1;
}
}
}
//UNION(x, y)
void unionSet(NODE *nodeX, NODE *nodeY) {
link(findSet(nodeX), findSet(nodeY));
}
/*
*GRAPH
*/
typedef struct EDGE {
NODE source;
NODE destination;
int weight;
} EDGE;
typedef struct GRAPH {
int V; //Number of vertices/nodes
int E; //Number of edges
EDGE *edge; //Array of edges
} GRAPH;
GRAPH *newGraph(int allocatedNumberOfVertices, int allocatedNumberOfEdges) {
GRAPH *graph = (GRAPH *)malloc(sizeof(GRAPH));
graph->E = 0; // intial state: no edges
graph->V = allocatedNumberOfVertices;
graph->edge = (EDGE *)malloc((allocatedNumberOfEdges) * sizeof(EDGE));
return graph;
}
void addEdge(GRAPH *graph, NODE srcNode, NODE dstNode, int weight) {
graph->edge[graph->E].source = srcNode;
graph->edge[graph->E].destination = dstNode;
graph->edge[graph->E].weight = weight;
graph->E += 1;
}
int compareEdges(const void *first, const void *second) {
const EDGE *firstEdge = (const EDGE *)first;
const EDGE *secondEdge = (const EDGE *)second;
if (firstEdge->weight == secondEdge->weight) {
return 0;
} else if (firstEdge->weight > secondEdge->weight) {
return 1;
} else {
return -1;
}
}
/*Kruskal's algorithm - returns an array of least weighted edges*/
EDGE *getMinimumSpanningTree(GRAPH *graph) {
int V = graph->V;
int E = graph->E;
int resultE = 0;
EDGE *result = (EDGE *)malloc(E * (sizeof(EDGE)));
//create a disjoint-set for every node
for (int e = 0; e < E; e++) {
makeSet(&(graph->edge[e].source));
makeSet(&(graph->edge[e].destination));
}
//sort edges of graph into nondecreasing order by weight
qsort(graph->edge, graph->E, sizeof(struct EDGE), compareEdges);
//finds a safe edge to add to the growing forest
for (int e = 0; e < E; e++) {
if (findSet(&(graph->edge[e].source))->data != findSet(&(graph->edge[e].destination))->data) {
result[resultE++] = *graph->edge;
unionSet(&(graph->edge[e].source), &(graph->edge[e].destination));
}
}
return result;
}
void KruskalDemo() {
GRAPH *graph = newGraph(6, 9);
NODE node[6];
for (int i = 0; i < 6; i++) {
node[i].data = i;
}
addEdge(graph, node[0], node[1], 3);
addEdge(graph, node[1], node[2], 1);
addEdge(graph, node[2], node[3], 1);
addEdge(graph, node[3], node[0], 1);
addEdge(graph, node[3], node[1], 3);
addEdge(graph, node[3], node[4], 6);
addEdge(graph, node[4], node[2], 5);
addEdge(graph, node[4], node[5], 2);
addEdge(graph, node[5], node[2], 4);
EDGE *MST = getMinimumSpanningTree(graph);
//we expect to have 5 vertices
for (int i = 0; i < 5; i++) {
printf("weight(%d, %d) = %d\n", MST->source.data, MST->destination.data, MST->weight);
}
}
int main() {
KruskalDemo();
return 0;
}

I solved: The problem was the algorithm and the fields of struct edge were not pointers:
Changed that:
typedef struct EDGE {
NODE source;
NODE destination;
int weight;
} EDGE;
to that:
typedef struct EDGE {
NODE *source;
NODE *destination;
int weight;
} EDGE;
And the algorithm to:
for (int e = 0; e < E; e++) {
if (findSet(graph->edge[e].source)->data != findSet(graph->edge[e].destination)->data) {
result[resultE++] = graph->edge[e];
unionSet(graph->edge[e].source,graph->edge[e].destination);
}
}

Related

How to traverse till a specified node in Weighted Undirected Graphs using BFS and DFS?

I have implemented the Weighted graph along with BFS and DFS. But I cannot figure a way out how to stop the traversal when a destination node (specified by user) is reached. Like user should enter the src and dest, and the BFS and DFS algorithm should print the tree until that specified node is reached. I have tried some things but I just cannot understand how to do this. I am attaching the code, any help would be appreciated.
#include "iostream"
#include "vector"
#include "queue"
#include "stack"
using namespace std;
typedef pair<int , int> Pair;
struct Edge{
int src, dest, weight;
};
class Graph{
public:
vector<vector<Pair>> adjacencyList;
Graph(vector<Edge> const &edges, int N)
{
adjacencyList.resize(N);
for(auto &edge: edges)
{
int src = edge.src;
int dest = edge.dest;
int weight = edge.weight;
adjacencyList[src].push_back(make_pair(dest,weight));
adjacencyList[dest].push_back(make_pair(src,weight));
}
}
};
void BFS(Graph const &graph, int src, vector<bool> &discovered)
{
queue<int> q;
discovered[src] = true;
q.push(src);
while(!q.empty())
{
src = q.front();
q.pop();
cout<<src<<" ";
for(int i = 0; i != graph.adjacencyList[src].size() ;i++)
{
if(!discovered[i])
{
discovered[i] = true;
q.push(i);
}
}
}
}
void DFS(Graph const &graph, int src, vector<bool> &discovered)
{
stack<int> stack;
stack.push(src);
while(!stack.empty()){
src = stack.top();
stack.pop();
if(discovered[src])
{
continue;
}
discovered[src] = true;
cout<<src<< " ";
for(int i = 0 ; i < graph.adjacencyList[src].size() ; i++)
{
if(!discovered[i])
{
stack.push(i);
}
}
}
}
void printGraph(Graph const &graph, int N)
{
for (int i = 0; i < N; ++i) {
for(Pair v: graph.adjacencyList[i])
{
cout<<"("<<i<<" , "<<v.first<<" , "<<v.second<<")";
}
cout<<endl;
}
}
int main()
{
vector<Edge> edges =
{
// `(x, y, w)` —> edge from `x` to `y` having weight `w`
{0,1}, {0,2}, {0,3},
{1, 2}, {2,4}, {3,3}, {4,4}
};
int N = 5;
Graph graph(edges,N);
// printGraph(graph,N);
vector<bool> discovered(N, false);
for(int i = 0; i<N; ++i)
{
if(!discovered[i])
{
BFS(graph, i, discovered);
}
}
cout<<endl;
vector<bool> discovered2(N, false);
for(int i = 0; i<N; i++)
{
if(!discovered2[i])
{
DFS(graph, i , discovered2);
}
}
cout<<endl;
printGraph(graph, N);
}
A recursive design makes this much simpler. here is the depth first version
// set stopNode global
......
bool cPathFinder::depthRecurse(int v)
{
// remember this node has been visted
visted[v] = true;
// is this the sop npde
if ( v == stopNode ) {
return true;
}
// look for new adjacent nodes
for (int w : myGraph.all_neighbors(v)) {
if (!visited[w])
{
// search from new node
if( depthRecurse(w) )
return true;
}
}
}

C++ EXC_BAD_ACCESS of Tree Root Node

I'm building an Octree for computer graphics. Trying to build the tree with following code:
void Accel::build() {
Octree *m_octree = new Octree(depth);
std::vector<uint32_t> indices(triangleCount);
for (uint32_t i = 0; i < triangleCount; ++i) {
indices[i] = i;
}
m_octree->root = m_octree->octreeBuild(m_bbox, indices, m_mesh);
}
The tree and tree node class are like the following:
Octree.h
class Octree {
public:
uint32_t totalNodes = 0;
uint32_t maxDepth = 0;
uint32_t totalDepth = 0;
std::vector<OctreeNode *> octreeVector;
OctreeNode *root;
Octree();
Octree(uint32_t d);
~Octree();
OctreeNode *octreeBuild(BoundingBox3f boundingBox, std::vector<uint32_t> indices, Mesh* mesh);
};
Octree.cpp
Octree::Octree(){}
Octree::Octree(uint32_t d): maxDepth(d) {}
Octree::~Octree(){
}
OctreeNode *Octree::octreeBuild(BoundingBox3f boundingBox, std::vector<uint32_t> indices, Mesh* mesh) {
if (indices.empty()) {
OctreeNode *node = nullptr;
octreeVector.push_back(node);
return node;
}
if (indices.size() <= 10 || totalDepth == maxDepth) {
OctreeNode *node = new OctreeNode(indices, boundingBox, true);
octreeVector.push_back(node);
totalNodes += 1;
return node;
}
if (totalDepth < maxDepth){
std::vector<uint32_t> nodeArray[8]; // Eight vector to store child node indices
BoundingBox3f boxArray[8] = {
boundingBox, boundingBox, boundingBox, boundingBox, boundingBox, boundingBox, boundingBox, boundingBox
}; // Eight bounding box, one for each child node
for (uint32_t i = 0; i < 8; ++i) { // Seperate bounding box
Point3f corner = boundingBox.getCorner(i);
Point3f center = boundingBox.getCenter();
Point3f minPoint = Point3f(std::min(corner.x(), center.x()), std::min(corner.y(), center.y()), std::min(corner.z(), center.z()));
Point3f maxPoint = Point3f(std::max(corner.x(), center.x()), std::max(corner.y(), center.y()), std::max(corner.z(), center.z()));
boxArray[i] = BoundingBox3f(minPoint, maxPoint);
}
for (uint32_t i = 0; i < static_cast<uint32_t>(indices.size()); i++) { // Check overlapping, store indices to cooresponding vector
BoundingBox3f triangleBox = mesh->getBoundingBox(i);
for (uint32_t j = 0; j < 8; ++j) {
if (boxArray[j].overlaps(triangleBox) && boxArray[j].contains(triangleBox.getCenter())) {
nodeArray[j].push_back(i);
break;
}
}
}
OctreeNode *node = new OctreeNode(indices, boundingBox, false); // Build the new node with children
octreeVector.push_back(node);
if (octreeVector.size() == 1) {
root = node;
}
totalDepth += 1;
for (uint32_t i = 0; i < 8; ++i) {
node->child[i] = octreeBuild(boxArray[i], nodeArray[i], mesh);
totalNodes += 1;
}
return node;
}
return nullptr;
};
I manage to build the program and the Octree::build went through without error messages. But after trying to search form the tree root, I got the EXC_BAD_ACCESS error. It seems like the root of my octree is lost. I'm new to C++, not sure if that's because the algorithms or the way I program with C++ was wrong. Thanks for any advice!

Get maximum edges count connected to a node in a graph

I made a program which adds nodes and edges between those nodes.Now i want to find which node has the maximum count of edges connected to it.Here is my code:
const int N = 15;
struct graf {
int key;
graf *next;
};
void init(graf *gr[]) {
for (int i = 0; i<N; i++) {
gr[i] = NULL;
}
}
int search_node(graf *gr[], int c) {
int flag = 0;
for (int i = 0; i<N; i++) {
if (gr[i]) {
if (gr[i]->key == c)flag = 1;
}
}
return flag;
}
int search_arc(graf *gr[], int c1, int c2) {
int flag = 0;
if (search_node(gr, c1) && search_node(gr, c2)) {
int i = 0;
while (gr[i]->key != c1)
i++;
graf *p = gr[i];
while (p->key != c2 && p->next != NULL)
p = p->next;
if (p->key == c2)
flag = 1;
}
return flag;
}
void add_node(graf *gr[], int c) {
if (search_node(gr, c))
printf("Edge existing !\n");
else {
int j = 0;
while (gr[j] && (j<N))j++;
if (gr[j] == NULL) {
gr[j] = new graf;
gr[j]->key = c;
gr[j]->next = NULL;
}
else
printf("Overflow !\n");
}
}
void add_arc(graf *gr[], int c1, int c2) {
int i = 0;
graf *p;
if (search_arc(gr, c1, c2))
printf("there is edge from node %s to node %s", c1, c2);
else {
if (!(search_node(gr, c1)))
add_node(gr, c1);
if (!(search_node(gr, c2)))
add_node(gr, c2);
while (gr[i]->key != c1)
i++;
p = new graf;
p->key = c2;
p->next = gr[i]->next;
gr[i]->next = p;
}
}
int get_graph_rank(graf*& gr,int i=0)
{
int max = NULL;
if (gr != NULL)
{
//i think to use recursion but i don't know how to start ...
}
return max;
}
int main() {
int c, k;
int menu = NULL, br = NULL;
graf *gr1[N];
init(gr1);
do
{
printf("1. add node\n");
printf("2. add edge\n");
printf("3.get the rang\n");
printf("0. exit\n");
do {
scanf_s("%d",&menu);
} while (menu<0 || menu>4);
switch (menu) {
case 1:
printf("enter edge: ");
scanf_s("%d", &c);
add_node(gr1, c);
break;
case 2:
printf("begining edge: ");
scanf_s("%d", &c);
printf("ending edge: ");
scanf_s("%d", &k);
add_arc(gr1, c, k);
break;
case 3:
get_graph_rank(*gr1);
break;
}
} while (menu != 0);
delete gr1;
}
I hope you could help me write the logic of the function which will return the value of the node ,which has the maximum edges connected to it , and if there is more than one node with the same count of edges connected , return NULL.Thanks in advice .....
Looks like the code uses a singly-linked list node for representing graph nodes. That means your nodes cannot have more than 1 (outgoing) edge. Not sure if such a graph representation is useful.
Another way is to represent your graph is use an array for graph node values and represent edges as an adjacency matrix N-by-N where each element is a bit specifying whether there is an edge from node A to node B.

C++ structures containing structures SIGSEGV

Let me paste the code first
#include <iostream>
#include <algorithm>
#define MAX 100
using namespace std;
int index;
struct node{
int key;
struct node *up;
int rank;
};
struct edge{
struct node *start, *end;
int weight;
};
struct graf{
struct node *tops[MAX];
int topsAmount;
struct edge *edges[MAX];
int edgesAmount;
};
void makeSet(struct node *z, int key){
z->up = z;
z->rank = 0;
z->key = key;
}
struct node *findSet(struct node *x){
if(x!=x->up)
x->up = findSet(x->up);
return x->up;
};
struct node *returnPath(struct node *x){
cout<<"klucz: "<<x->key<<" ranga: "<<x->rank<<endl;
if(x!=x->up)
{
returnPath(x->up);
}
}
void link(struct node *x, struct node *y){
if(x->rank>y->rank)
{
y->up=x;
}
else
{
x->up=y;
if(x->rank == y->rank)
y->rank++;
}
}
void unionFun(struct node *x, struct node *y){
link(findSet(x), findSet(y));
}
bool acompare(edge lhs, edge rhs) { return lhs.weight < rhs.weight; }
struct edge *MSTKruskal(struct graf *G){
struct edge *A = new edge[MAX];
index=0;
for(int i=0; i<G->topsAmount; i++)
{
makeSet(G->tops[i],0);
}
sort(G->edges[0], G->edges[G->edgesAmount-1], acompare);
for(int i=0; i<G->edgesAmount; i++)
{
if(findSet(G->edges[i]->start) != findSet(G->edges[i]->end))
{
A[index].start = G->edges[i]->start;
A[index].end = G->edges[i]->end;
A[index].weight = G->edges[i]->weight;
index++;
unionFun(G->edges[i]->start, G->edges[i]->end);
}
}
return A;
}
int main()
{
struct node *values[11];
for(int i=0; i<10; i++)
{
values[i] = new node;
makeSet(values[i],i);
}
unionFun(values[0], values[1]);
unionFun(values[2], values[3]);
unionFun(values[1], values[2]);
unionFun(values[5], values[6]);
unionFun(values[7], values[8]);
unionFun(values[3], values[5]);
unionFun(values[0], values[7]);
for(int i=0; i<10; i++)
{
cout<<"sciezka klucza "<<i<<endl;
returnPath(values[i]);
}
struct graf *Graf = new graf;
for(int i=0; i<10; i++)
{
Graf->tops[i] = values[i];
Graf->topsAmount++;
}
struct edge *Edges = new edge[4];
Edges[0].start = values[1];
Edges[1].start = values[2];
Edges[2].start = values[3];
Edges[3].start = values[4];
Edges[0].end = values[5];
Edges[1].end = values[6];
Edges[2].end = values[7];
Edges[3].end = values[8];
Edges[0].weight = 10;
Edges[1].weight = 12;
Edges[2].weight = 11;
Edges[3].weight = 13;
Graf->edges[0] = Edges[0]; //this line was deleted after I found out that I can't compile it
Graf->edges[0]->weight = 0;
return 0;
}
I want to set new graf so firstly in for loop I add tops to my structure and it works then I want to add edges and problem appears. I thought I can just create another array of structures edge and then just set same array in Graf on same values (Graf->edges[0] = Edges[0]; last lines of the code) but it didn't compile, so I wanted to set every value of structure edge in array Graf separately (start = start, end = end etc) but debugger shows SIGSEGV on last line (Graf->edges[0]->weight = 0;) how can I fix it?
Edges[0] has type edge, but Graf->edges[0] has type edge*, i.e. the types are incompatible, which is why the assignment is not allowed.
You probably want to take the address of Edges[0] like so:
Graf->edges[0] = &Edges[0];

Disjoint set data structure : track size of each tree

Below is my implementation to keep track of the size of each tree in the disjoint set forest.
Can you please tell me what is wrong with it ? I am trying to solve UVa problem https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3638
#include <iostream>
#include <cstdio>
#include <unordered_map>
using namespace std;
class Node {
public :
int id;
Node *parent;
unsigned long long rank;
Node(int id) {
this->id = id;
// this->data = data;
this->rank =1; //size here
this->parent = this;
}
friend class DisjointSet;
};
class DisjointSet {
unordered_map<int,Node*> nodesMap;
Node *find_set_helper(Node *aNode) {
if (aNode == aNode->parent) {
return aNode->parent;
}
return find_set_helper(aNode->parent);
}
void link(Node *xNode,Node *yNode) {
if( xNode->rank > yNode->rank) {
yNode->parent = xNode;
xNode->rank += yNode->rank;
}
// else if(xNode-> rank < yNode->rank){
// xNode->parent = yNode;
// yNode->rank += xNode->rank;
// }
else {
xNode->parent = yNode;
yNode->rank += xNode->rank;
}
}
public:
DisjointSet() {
}
void AddElements(int sz) {
for(int i=0;i<sz;i++)
this->make_set(i);
}
void make_set(int id) {
Node *aNode = new Node(id);
this->nodesMap.insert(make_pair(id,aNode));
}
void Union(int xId, int yId) {
Node *xNode = find_set(xId);
Node *yNode = find_set(yId);
if(xNode && yNode)
link(xNode,yNode);
}
Node* find_set(int id) {
unordered_map<int,Node*> :: iterator itr = this->nodesMap.find(id);
if(itr == this->nodesMap.end())
return NULL;
return this->find_set_helper(itr->second);
}
~DisjointSet(){
unordered_map<int,Node*>::iterator itr;
for(itr = nodesMap.begin(); itr != nodesMap.end(); itr++) {
delete (itr->second);
}
}
};
int main() {
int n,m,k,first,cur;
//freopen("in.in","r",stdin);
scanf("%d %d",&n,&m);
while(n != 0 || m != 0) {
DisjointSet *ds = new DisjointSet();
ds->AddElements(n); // 0 to n-1
//printf("\n n = %d m = %d",n,m);
for(int i=1;i<=m;i++) {
scanf("%d",&k);
//printf("\nk=%d",k);
if ( k > 0 ) {
scanf("%d",&first);
for(int j=2;j<=k;j++) {
scanf("%d",&cur);
ds->Union(first,cur);
}
}
}
Node *zeroSet = ds->find_set(0);
// unsigned long long count = ds->getCount(zeroSet->id);
printf("%llu\n",zeroSet->rank);
delete ds;
scanf("%d %d",&n,&m);
}
return 0;
}
The link function in the above code does the job of updating the tree size.
The solution to the problem is to find the set which elements 0 belongs to and get the size of the representative element of the set.
But I am getting wrong answer with this code.
Can you please help me
In your Union function, check if both nodes are already in the same set.
if(xNode && yNode && xNode != yNode)
link(xNode,yNode);