I'm thinking the way to implement the graph which is linked list based. But, as far as I know, linked list can only access to next list (or previous too if doubly) and vertex from graph can access any other vertex unless it doesn't have an edge to some vertex. These two different features break my idea to build a graph.
If my vertex(or node) class(or structure) has pointer to another vertex,
class Vertex
{
Vertex *link; //edge to another veretex
int item; //item in vertex
}
and my graph class looks like
class GraphClass
{
Vertex **Graph; //Graph itself
int VertexQuantity; // number of vertex in graph
}
I can add vertex into graph with function addVertex() but when try to connect two vertexes, starts to losing my head. What I considering to build addEdge() function is
two vertexes must exist in graph
two vertexes shouldn't connected yet
and a function below is my addEdge() function which I'm working now.
void addEdge(Graph *g, Vertex *source, Vertex *destination)
{
unsigned index, sourceIndex;
Vertex *temp;
// if source or destination is not exist in graph
if((sourceIndex = searchVertex(g, source) < 0 || searchVertex(g, destination) < 0))
return;
// if source and destination are already connected
if(checkConnection(g, sourceIndex, source, destination) < 0 || sourceIndex < 0)
return;
temp = g->Graph[sourceIndex];
temp->link = destination;
}
This is my question. Let's say, v1 is vertex and connected to v2. What should I do if I wanna make a connection between v1 and v3? v1 only has its link to point some vertex, if I change vertex's next pointer as array to point multiple vertex, it breaks the rule of linked list.
Usually this is done by having a linked list of all the nodes that your current node is connected too. If this is too confusing, start with a vector or array of pointers to all the nodes that your current node connects to, then implement that vector/array using a linked list.
Related
I am currently working on getting models to work efficiently in a ray tracer implemented as an OpenGL compute shader. I already figured out how to construct the BVH and have implemented this on the CPU side. The problem I now have is that I can't figure out how to handle the tree traversal on the GPU side.
This is a snippet of something I came up with:
struct BVHNode {
vec3 AABBMin;
vec3 AABBMax;
BVHNode Children[2];
int NumTriangles;
Triangle Triangles[MAX_TRIANGLES]; // Waste of memory, non leaf nodes dont have any triangles but still have a fully allocated array
};
struct Mesh {
BVHNode BVH;
Material Material;
};
layout(std140, binding=2) buffer MeshSSBO {
Mesh Meshes[];
} meshSSBO;
This was in my opinion the most straightforward way of doing it, just a normal tree that can be traversed easily with recursion or a stack. Sadly, GLSL supports neither of these so I am not sure how to traverse this tree.
So I have a couple questions:
How to traverse a full binary tree of unknown depth in GLSL?
The algorithm I need is very easily implemented with a stack or recursion, but I don't know how to do it without those. This is a snippet of C# that shows what I want to do.
Stack<BVHNode> stack = new Stack<BVHNode>();
stack.Push(root);
while(stack.Count > 0) {
var currentNode = stack.Pop();
if(rayIntersects(ray, currentNode)) {
// Check triangles if leaf
if (node.NumTriangles > 0) {
for (int i = 0; i < node.NumTriangles; i++) {
if (rayIntersects(ray, currentNode.Triangles[i])) {
// handle intersection
}
}
}
// Otherwise continue traversal
else {
stack.Push(currentNode.Children[0]);
stack.Push(currentNode.Children[1]);
}
}
}
Is loading the meshes and BVHs through an SSBO an efficient way to get this data to the shader?
The vertices are loaded through a separate SSBO, the Triangle struct only contains indices to this vertex array.
I have search but can't find a anything specific to my case.
I wanna implement a graph in c++ using linked list only. My structure is as below:
class Vertex
{
public:
Vertex(std::string name = "none");
private:
std::string name;
Edge *edges;
Vertex *next;
Runnable *runnables;
};
class Edge
{
public:
Edge();
private:
Vertex *connectsTo;
Edge *next;
};
class TaskGraph{
public:
TaskGraph();
private:
Vertex *head;
};
I have a method to add vertices to the graph
void addVertex(TaskGraph* taskGraph, const std::string&);
This method works well as I can print out all the vertices in the graph. On the otherhand, to add directed edge, I did something like this:
void MyGraph::addEdge(TaskGraph* taskGraph, const string& src, const string& dest){
//get to the source vertex: this is ok
//get to the destination vertex: this is also ok
//add edge : the problem is here // s is source vertex while d is destination vertex.
Edge *e = new Edge;
e->connectsTo = d;
if(s->edges == 0){
s->edges = e;
}else{
s->edges->next = e;
}
}
After adding say 5 edges, only two is actually added (i.e. the first and list edges, others are being replaced). I figure out it's because of this line: "s->edges->next = e;" but can't figure out how to implement it correctly. Please help!!!
Thanks
You are breaking your list. when you insert the edge. So you first case always works. you just add e are your edge.
The other case will add e as second edge but will loose all other edges previously added.
try this instead:
//add edge : the problem is here
Edge *e = new Edge;
e->connectsTo = d;
//If there is already a list node pointing to in s->edges...
if(s->edges != 0){
//Then apply the existing list to the back of the new node.
// this add the exiting edges to the new one so you do not break the list.
e->next = s->edges;
}
//Apply e as the head of the list (pointing to it via s->edges).
s->edges = e;
This algorithm adds the new edge at the front of the list so they will appear in reverse order as the order you added them in.
To keep edges in the same order as they were inserted you can do as suggested below looping or adding a tail pointer for the last edge in the list..
The most important here is that you understand what you where doing wrong.
You started with
S->edges->NULL
you added an edge E1 you you get
S->edges->E1.next->NULL
Now you added the second edge E2 and:
S->edges->E1.next->E2.next->NULL
So far so good. But when you add E3 this what what happened:
S->edges->E1.next->E3.next->NULL lost link to E2.next->NULL
This is why you only had 2 edges in your list no matter how many edges you tried to add. It is also called a memory leak because you have lost all references to the E2 instance and you cannot clean up those objects.
Ok, that said this is and example implementation for what the others where talking about in the comments below about how to keep the list in the same order as the edges you added. So E1 is first E2 second, etc...:
class Vertex
{
public:
Vertex(std::string name = "none");
private:
std::string name;
Edge *edges;
Edge *lastEdge; // this will keep track of the last edge in the list.
// with this pointer you avoid having to loop through all
// the edges every time to add to the end.
Vertex *next;
Runnable *runnables;
};
void MyGraph::addEdge(TaskGraph* taskGraph, const string& src, const string& dest)
{
//get to the source vertex: this is ok
//get to the destination vertex: this is also ok
//add edge : the problem is here // s is source vertex while d is destination vertex.
Edge *e = new Edge;
e->connectsTo = d;
if(s->edges == 0)
{
s->edges = e;
// set the last edge to point to the first item.
s->lastEdge = e;
}
else
{
// In this case the logic is simple you already know that
// the list is not empty and that lastEdge is pointing at the
// last edge in the list so just make the current lastEdge
// point to the new edge. This will grow your list with e at
// the end.
// Then update lastEdge to point to the new edge you just added.
// so that is it pointing to the end of the list again.
s->lastEdge->next = e;
s->lastEdge = e;
}
}
Let me first state that I just want direction, not necessarily actual code, unless a small snippet is the only way to get the point across.
I need to create a DIRECTED graph data structure using an adjacency list or matrix in C++, and add vertices/edges from standard input, which means dynamically.
I think I'd be able to create a graph fine if I was able to instantiate a set of Vertices first, then create edges and add them to the graph, but I don't understand how it is possible to add an edge which contains a vertex that hasn't been instantiated yet.
for example, the first line from standard input reads:
Miami -> New York/1100 -> Washington/1000 -> albuquerque/1700
How am I supposed to add an edge from Miami to New York if the New York vertex hasn't been added to the graph yet?
Thanks for the direction everyone!
how it is possible to add an edge which
contains a vertex that hasn't been instantiated yet.
Simple: instantiate it..
I do not see any issue with this. Assume V to be the vertex set seen so far. V is initially empty. As you read the input x->y, you get its end points (x and y). If any one of them is not instantiated (i.e., not in V), you instantiate it and add it to the vertex set.
Another way to look to it: imagine we are defining the graph by its edge set E. By definition any edge is a pair of vertices which in turn defines the vertex set of the graph.
How about you resize the adjacency list each time a new unique node comes in? You can maintain a set of unique node values and use its size to adjust the size of the adjacency list each time you have to add a node. Below is a some code that does the same.
class Graph
{
public:
// Add links in the graph
void addLink(int id1, int id2){
// Add to hashset
uniqueNodes.insert(id1);
uniqueNodes.insert(id2);
// Resize on the adjacency list based on how many nodes exists in the uniqueNodes set
adjList.resize(uniqueNodes.size());
// Make the connections assuming undirected graph
adjList[id1].push_back(id2);
adjList[id2].push_back(id1);
}
// Print the graph
void printGraph(){
for(int i = 0; i < adjList.size(); i++){
cout << i << ":";
for(auto it = adjList[i].begin(); it != adjList[i].end(); it++)
cout << *it << "->";
cout << "NULL\n";
}
}
private:
// Adjacency list for the graph
vector<list<int>> adjList;
// Hashset to help define the size of the adjacency list as nodes come in
set<int> uniqueNodes;
};
I would like to get the VID (vertex ID) after I have added a single vertex to an existing graph. I current get a vertex_set after adding the new vertex and loop through to the end of the vertex set (assuming this is always the last added vertex even in the event of a earlier one being deleted?). I need to test if deleting a vertex from the middle of the set changes the VIDs still. But I am sure there must be a better (read more efficient way) of doing this.. The code below is what I currently use.
Any help appreciated as I am new to iGraph.
// add into graph
igraph_integer_t t = 1;
if(igraph_add_vertices(user_graph, t, 0) != 0)
{
::MessageBoxW(NULL, L"Failed to add vertex to iGraph, vertex not added.", L"Network Model", MB_ICONSTOP);
return false;
}
/* get all verticies */
igraph_vs_t vertex_set;
igraph_vit_t vit;
igraph_integer_t vid = 0;
igraph_vs_all(&vertex_set);
igraph_vit_create(user_graph, vertex_set, &vit);
// must be a better way - look for starting from end.
while (!IGRAPH_VIT_END(vit))
{
vid = IGRAPH_VIT_GET(vit);
IGRAPH_VIT_NEXT(vit);
}
// add vid to vertex ca
ca->graphid = (int)vid;
// Add new vertex to local store
vm->CreateVertex(ca);
// cleanup
igraph_vit_destroy(&vit);
igraph_vs_destroy(&vertex_set);
Vertex IDs (and also edge IDs) in igraph are integers from zero up to the number of vertices/edges minus one. Therefore, if you add a new vertex or edge, its ID will always be equal to the number of vertices/edges before the addition. Also, if you delete some edges, the IDs of existing edges will be re-arranged to make the edge ID range continuous again. Same applies for the deletion of vertices, and note that deleting some vertices will also re-arrange the edge IDs unless the deleted vertices were isolated.
By now, I have used the following algorithm for finding the strongly connected components of a graph.
call DFS(G) to compute the finishing time f[v] for every vertex v, sort the vertices of G in decreasing order of their finishing time;
compute the transpose GT of G;
Perform another DFS on G, this time in the main for-loop we go through the vertices of G
in the decreasing order of f[v];
output the vertices of each tree in the DFS forest (formed by the second DFS) as a separate
strongly connected component.
.
But I was wondering if it is possible to find all the strongly connected components in only one DFS.
Any help in this regard would be highly appreciated.
Check out, Algorithm Design Manual by Steven Skiena. It calculates SCC in one DFS. It's based on the concept of oldest reachable vertex.
Initialize each vertex's reachable vertex and SCComponent# to itself in the beginning.
low[i] = i;
scc[i] = -1;
Do a DFS on the digraph, you are interested only in back edges and cross edges because these two edges will tell you if you've encountered a back edge and entering 1 component from another.
int edge_classification(int x, int y)
{
if (parent[y] == x) return(TREE);
if (discovered[y] && !processed[y]) return(BACK);
if (processed[y] && (entry_time[y]>entry_time[x])) return(FORWARD);
if (processed[y] && (entry_time[y]<entry_time[x])) return(CROSS);
printf("Warning: unclassified edge (%d,%d)\n",x,y);
}
So when you encounter these edges, you set reachable vertex[] recursively, based on the entry times.
if (class == BACK) {
if (entry_time[y] < entry_time[ low[x] ] )
low[x] = y;
}
if (class == CROSS)
{
if (scc[y] == -1) /* component not yet assigned */
if (entry_time[y] < entry_time[ low[x] ] )
low[x] = y;
}
A new strongly connected component is found whenever the lowest reachable vertex from vertex 'v' is itself (loop can say, a->b->c->a, lowest reachable vertex of a is a).
process_vertex_early(int v)
{
push(&active,v);
}
After DFS for a vertex is complete (DFS for it's neighbors would have been completed too), check the lowest reachable vertex for it:
if (low[v] == v)
{ /* edge (parent[v],v) cuts off scc */
pop_component(v);
}
if (entry_time[low[v]] < entry_time[low[parent[v]]])
low[parent[v]] = low[v];
pop_component(...) just pops from the stack until this component is found. If a->b->c->a is scanned the stack will have a(bottom)->b->c(top).. pop until vertex 'a' is seen. You get an SCC for 'a'..and similarly you get all connected components in one DFS.
I found this on the Wikipedia page for Strongly connected component:
Kosaraju's algorithm, Tarjan's algorithm and the path-based strong
component algorithm all efficiently compute the strongly connected
components of a directed graph, but Tarjan's and the path-based
algorithm are favoured in practice since they require only one
depth-first search rather than two.
I think this quite answers your question :)