C++ structures containing structures SIGSEGV - c++

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];

Related

Constructor doesn't update class member variables

So I am trying to implement a hash table and I am having trouble seeing what is wrong in my class or constructor. In summary when I try to reach an element of hash table array, I can in constructor, but I cannot in the member function (I get seg fault), which leads me to believe there is something wrong with my class/ constructor doesn't work.
website::website(int input) //Constructor
{
SIZE = input;
node** hashtable = new node * [SIZE];
for (int i = 0; i<SIZE; i++)
{
hashtable[i] = NULL;
if(!hashtable[i])
{
cout<<"It works at "<<i<<"th"<<endl;//This is to check
}
}
}
int website::hashfunction(const char array []) //Hash function
{
int inputsize = strlen(array);
int value = 0;
for (int i=0; i< inputsize; i++)
{
value = value + int(array[i]);
}
value = value % SIZE;
return value;
}
These functions do what they are supposed to do
but when I run this function. I get seg fault at hashtable[place]==NULL level.
int website::insert(const mainentry& input)
{
int place = 0;
node*temp = new node;
/* Ignore this part
temp->data.topic = new char[strlen(input.topic)+1];
strcpy(temp->data.topic, input.topic);
temp->data.url = new char[strlen(input.url)+1];
strcpy(temp->data.url, input.url);
temp->data.summary = new char[strlen(input.summary)+1];
strcpy(temp->data.summary, input.summary);
temp->data.review = new char[strlen(input.review)+1];
strcpy(temp->data.review, input.review);
temp->data.rating = input.rating;
*/
place = hashfunction(temp->data.topic);
cout<<"Place is: "<<place<<endl; //Hash function works correctly
if (hashtable[place]== NULL) // THIS IS THE PART I GET SEG FAULT
{
hashtable[place] = temp;
temp->next = NULL;
return 1;
}
else
{
temp->next = hashtable[place];
hashtable[place] = temp;
return 1;
}
return 0;
}
Here is my class:
class website
{
public:
website(int input);
// ~website();
int insert(const mainentry & input);
int retrieve( char [], mainentry output [] );
int edit (mainentry & input);
int remove();
int display(char []);
int display_all();
int hashfunction(const char []);
private:
int SIZE;
node ** hashtable;
};
I am assuming I am making a beginner's mistake but I can't see what is going on, if anyone can direct me, I'd appreciate it.
You are shadowing the class's hashtable variable in the constructor by writing:
website::website(int input) //Constructor
{
SIZE = input;
node** hashtable = new node * [SIZE]; //<<-- Shadowing. you are declaring a local scope veriable called hastable, and not using the class's instance.
}
node** hashtable = new node * [SIZE];
should be
hashtable = new node * [SIZE];

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

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);
}
}

How to create a linked list in C++?

I got these two structs
struct CamelZombie{
int hp;
int attack;
CamelZombie *next;
};
struct list_of_cz{
CamelZombie *head;
};
I've made a function to create linked list with given value:
void createCamelZombie(list_of_cz *&pZ, int z_hp, int z_attack, int N){
pZ = new list_of_cz;
pZ->head->hp = z_hp;
pZ->head->attack = z_attack;
CamelZombie *temp1 = pZ->head;
CamelZombie *temp2 = NULL;
for (int i = 0; i < N - 1 ; i++){
temp2 = new CamelZombie;
temp2->hp = z_hp;
temp2->attack = z_attack;
temp1->next = temp2;
temp1 = temp2;
}
}
Then i put it in function main like this, but then the propram crashed, don't know why.
list_of_cz *pZ = NULL;
createCamelZombie(pZ, z_hp, z_attack, N);
while (pList->head != NULL && pZ != NULL){
atPlant(numPlant(pList) - 1, pList)->hp -= pZ->head->attack;
if (atPlant(numPlant(pList) - 1, pList)->hp <= 0) deletePlant(numPlant(pList) - 1, pList);
int count = 0;
CamelZombie *z_temp;
z_temp = pZ->head;
while (z_temp){
if (count == 0) z_temp->hp -= allPlantAttack(pList, numPlant(pList) - 1);
else z_temp->hp -= allLaserAttack(pList); //trouble right here
if (z_temp->hp <= 0) deleteCamelZombie(pZ, count);
z_temp = z_temp->next;
count++;
}
Seem like i miss something when writing void createCamelZombie() 'cause the compiler tells me that z_temp->hp don't have a value. Please help me!
Preferably use an existing container like std::vector or std::list
#include <iostream>
#include <string>
#include <list>
struct CamelZombie{
std::string name; //added for demonstration purposes
int hp;
int attack;
//pointer to next zombie not required
};
std::list<CamelZombie> createCamelZombie2(int z_hp, int z_attack, int N) {
std::list<CamelZombie> result;
for (int i = 0; i < N; i++){
CamelZombie newZombie;
newZombie.name = "Zombie"+std::to_string(i);
newZombie.hp = z_hp;
newZombie.attack = z_attack;
newZombie.next = NULL;
result.push_back(newZombie);
}
return result;
}
Use the code like this.
int main() {
std::list<CamelZombie> listOfZombies2 = createCamelZombie2(10,20,10);
for(std::list<CamelZombie>::iterator list_iter = listOfZombies2.begin();
list_iter != listOfZombies2.end(); list_iter++)
{
std::cout<<list_iter->name<<std::endl;
}
}
If you really want to use your own linked list try the code below.
A seperate struct (list_of_cz) for the list is not required. Each zombie links to the next zombie. So just keep a pointer to the first zombie.
createCamelZombie function returns a pointer to the first zombie in the list (no need to use the function parameter (list_of_cz *&pZ) to get the zombie list)
Too many underscores and Z makes the code hard to read.
If you use pointers you need to clean up memory yourself.
.
struct CamelZombie{
std::string name; //added for demonstration purposes
int hp;
int attack;
CamelZombie *next;
};
CamelZombie* createCamelZombie(int z_hp, int z_attack, int N){
CamelZombie *result = NULL;
CamelZombie *work = NULL; //keep track of the last node in the list
for (int i = 0; i < N; i++){
//create new zombie
CamelZombie *newZombie = new CamelZombie();
newZombie->name = "Zombie"+std::to_string(i);
newZombie->hp = z_hp;
newZombie->attack = z_attack;
newZombie->next = NULL;
if (result==NULL) {
result = newZombie;
work =result;
} else {
work->next = newZombie;
work = newZombie;
}
}
return result;
}
Example of how to use the code.
int main() {
CamelZombie *listOfZombies = createCamelZombie(10,20,10);
CamelZombie *work = listOfZombies;
// print zombie names to screen ---------
while (work!=NULL) {
std::cout << work->name << std::endl;
work = work->next;
}
And free memory.
work = listOfZombies;
while (work!=NULL) {
CamelZombie *temp =work->next;
delete work;
work = temp;
}

Create a randomly connected set of nodes?

I'm trying to write a function, generate_labyrinth(), that creates a fixed number of randomly connected nodes. Each node is connected with three other nodes.
Here is what I have now:
labyrinth.h:
#ifndef LABYRINTH_H
#define LABYRINTH_H
// node
class Room {
public:
Room ()
: room_number(0), left_door(nullptr),
center_door(nullptr), right_door(nullptr) { }
// data member
int room_number;
// pointers to other nodes
Room* left_door;
Room* center_door;
Room* right_door;
};
//=================================================
class Labyrinth {
public:
Labyrinth (int s) : size(s) { generate_labyrinth (); }
private:
// number of nodes
int size;
// root node
Room* entrance;
// Helper functions
int random_number (int from, int to);
int random_number_without_i (int min, int max, int i);
// Initialiazation function
void generate_labyrinth ();
};
#include "labyrinth.cpp"
#endif
labyrinth.cpp:
// Class Labyrinth member implementations
int Labyrinth::random_number (int min, int max) {
static bool seed_initialized = false;
if (!seed_initialized) {
seed_initialized = true;
srand((unsigned int) time(NULL));
}
return rand() % (max - min + 1) + min;
}
int Labyrinth::random_number_without_i (int min, int max, int i) {
int res = random_number(min, max);
while (res == i){
res = random_number(min, max);
}
return res;
}
void Labyrinth::generate_labyrinth () {
// create "size" number of nodes
entrance = new Room[size];
// initialize Room (node) data members
for (auto i = 0; i < size; ++i) {
entrance[i].room_number = i;
}
// connect each room with three others
int first_room = 1;
int last_room = size - 1;
for (int i = 1; i < size; ++i) {
// avoid connecting a room with itself
int left_goes_to = random_number_without_i (first_room, last_room, i);
int center_goes_to = random_number_without_i (first_room, last_room, i);
int right_goes_to = random_number_without_i (first_room, last_room, i);
entrance[i].left_door = (&entrance[left_goes_to]);
entrance[i].center_door = (&entrance [center_goes_to]);
entrance[i].right_door = (&entrance [right_goes_to]);;
}
// TEST IF NODES POINT TO EACH OTHER
for (auto i = 0; i < size; ++i) {
if (entrance[i].left_door == nullptr || entrance[i].center_door == nullptr ||
entrance[i].right_door == nullptr) {
std::cout <<"Uninitialized pointer value\n";
}
}
getchar();
}
main:
#include <iostream>
#include <time.h>
#include "labyrinth.h"
//=================================================
int main()
{
int cave_size = 20;
Labyrinth cave(cave_size);
}
It appears that after the node initialization in generate_labyrinth () the three pointers, left_room, center_room, right_room remain uninitialized, i.e. the output I get is :
Uninitialized pointer value
Questions:
Why aren't the pointers in the nodes initialized?
Is there another way to generate a randomly connected set of nodes?
Note: I'm not using an insert() function as the number of nodes is fixed and determined during the construction of the data structure.
You generate connections for first_room to last_room, which are rooms 1 to size-1.
// connect each room with three others
int first_room = 1;
int last_room = size - 1;
for (int i = 1; i < size; ++i) {
But when you check the connections you start with room 0 (probably supposed to be the entrance itself).
// TEST IF NODES POINT TO EACH OTHER
for (auto i = 0; i < size; ++i) {

C++ Implementation of Held-Karp and speed

I'm trying to speed up my implementation of the Held-Karp Algorithm and I've been trying to figure why after nine points, it starts to become increasingly slow. I'm also utilizing xlib to help with illustrating the graph but I don't think that's the issue.
double GetMinimumRoute(int startVertex, std::vector<int> Set, Node* root)
{
printf("%d\n", CountRecursive);
CountRecursive++;
if(Set.empty())
{
Node node;
root->Nodes.clear();
root->Nodes.push_back(node);
root->Nodes.at(0).Value = Vertices[0];
root->Nodes.at(0).Selected = true;
root->CountNodes = 0;
return AdjancyMatrix[startVertex][0];
}
double totalCost = 999999999;
int selectedIndex = 0;
//root->Nodes.clear();
for(unsigned int i=0; i<Set.size(); i++)
{
Node node;
node.Selected=false;
root->Nodes.push_back(node);
root->Nodes.at(i).Value = Set.at(i);
int costOfVisitingCurrentNode = AdjancyMatrix[startVertex][Set.at(i)];
std::vector<int> newSet(Set);
newSet.erase(newSet.begin()+i);
int costOfVisitingOtherNodes = GetMinimumRoute(Set.at(i), newSet, &(root->Nodes.at(i)));
int currentCost = costOfVisitingCurrentNode + costOfVisitingOtherNodes;
if(totalCost > currentCost)
{
totalCost = currentCost;
selectedIndex = i;
}
}
root->Nodes.at(selectedIndex).Selected = true;
return totalCost;
}