Creating an adjacency List for DFS - c++

I'm having trouble creating a Depth First Search for my program. So far I have a class of edges and a class of regions. I want to store all the connected edges inside one node of my region. I can tell if something is connected by the getKey() function I have already implemented. If two edges have the same key, then they are connected. For the next region, I want to store another set of connected edges inside that region, etc etc. However, I am not fully understanding DFS and I'm having some trouble implementing it. I'm not sure when/where to call DFS again. Any help would be appreciated!
class edge
{
private:
int source, destination, length;
int key;
edge *next;
public:
getKey(){ return key; }
}
class region
{
edge *data;
edge *next;
region() { data = new edge(); next = NULL; }
};
void runDFS(int i, edge **edge, int a)
{
region *head = new region();
aa[i]->visited == true;//mark the first vertex as true
for(int v = 0; v < a; v++)
{
if(tem->edge[i].getKey() == tem->edge[v].getKey()) //if the edges of the vertex have the same root
{
if(head->data == NULL)
{
head->data = aa[i];
head->data->next == NULL;
} //create an edge
if(head->data)
{
head->data->next = aa[i];
head->data->next->next == NULL;
}//if there is already a node connected to ti
}
if(aa[v]->visited == false)
runDFS(v, edge, a); //call the DFS again
} //for loop
}

assuming n is total number of edges, k is final number of regions.
Creating adjacency list for the requisite DFS might be too costly O(n^2) (if k=1 i.e. all edges belong to same region) and hence dfs will cost you O(V+E) i.e. O(n^2) in the worst case.
Otherwise problem is easily solvable in O(n * log(k)) as follows:
Traverse through all edges adding them to the head of corresponding regions (using balanced bst eg. stl-map) [you may use hashing for this too]
traverse through all the regions and connect them in requisite linear fashion
No guaranteed O(n) solution exists for the problem I guess..

I tried to implement a adjacency list creating function.The next pointer of adj_list struct takes you down the adjacency list(there is no relationship between 2 nodes connected by next) and the list pointer is the adjacency list. The node has the address of the adj_list which has its adjacency list.
struct node{
int id;
adj_list* adj;
};
struct adj_list{
adj_list* next;
adj_list* list;
node* n;
adj_list(node& _n){
n = &(_n);
next = NULL;
list = NULL;
}
};
node* add_node(int id,std::queue<int> q , node* root)
{
node* n = new node(id);
adj_list* adj = new adj_list(*n);
n->adj = adj;
if(root == NULL){
return n;
}
std::queue<adj_list*> q1;
while(1){
adj_list* iter = root->adj;
if(q.empty())break;
int k = q.front();
q.pop();
while(iter){
if(iter->n->id == k){
q1.push(iter);
adj_list* temp = iter->list;
iter->list = new adj_list(*n);
break;
}
iter = iter->next;
}
}
adj_list* iter = root->adj;
while(iter->next){
iter = iter->next;
}
iter->next = adj;
while(!q1.empty()){
adj_list* temp = q1.front();
q1.pop();
adj->list = temp;
adj = temp;
}
return root;
}

Related

Make RadixSort with linked lists on C++

I'm learning C++ and learning linked lists. I'm currently trying to make a radix sort for this type of lists, but my approach is not working so I was wondering if anyone could advice me on how to do it. Here's my code:
void simpleList::radixSort() {
for (int i = 0; i < numberOfDigits(); i++){
Node * tmp = firstNode;
for (int j = 0; j < counter(); j++){
int pow = 10;
for (int k = 0; k < 10; k++){
if (tmp -> data % pow == k){
insertFirst(tmp->data);
tmp = tmp -> next;
}
pow= pow * 10;
}
}
}
}
The function numberOfDigits() gets you the amount of digits on the max number of the list, and counter() the amount of elements in the list. Also insertFirst() puts the number at the beggining of the list.
A few notes to help you on your way:
Radix Sort
A radix sort is any kind of (stable n-ary bucket sort) repeated until you run out of digits in your sort keys. Make your life simple: use binary as your radix.
Keys
You are using int values in your list, but that need not be the case. In general, you need a value→key function that returns an integer key for each element of your list, where “equivalent” elements return the same key. For a list of integers the value→key function is the identity function, so easy enough.
For convenience, I will use lambdas for the value→key functions below.
Reducing Passes
You can reduce the number of times you bucket sort to only those bits that are not the same for all keys. Before the first pass through your list, you do not know anything about the keys, so we can gather information at the same time as the first bucket sort:
key_type key_mask = 0; // bits to sort
key_type common_mask = ~0; // (bits set in all keys)
auto value_to_bucket_fn = [&]( const T & element )
{
// here we gather information about the keys
key_type key = user_supplied_value_to_key_fn( element );
key_mask |= key;
common_mask &= key;
// here we return our first bucket key == bit 0
return key & 1;
};
binary_bucket_sort( value_to_bucket_fn );
Once we have made that first pass, we can get a bitmask indicating which bits need sorting in our keys:
key_mask ^= common_mask; // key_mask ← set bits == bits to sort
All remaining passes can now be managed with a simple loop, ending when we run out of bits needing sorting:
for (int shift = 1; key_mask >>= 1; shift++)
if (key_mask & 1)
binary_bucket_sort( [&]( const T & element )
{
return (user_supplied_value_to_key_fn( element ) >> shift) & 1;
} );
Bucket Sort
A linked list is perfect for bucket sorts of large, unwieldly objects. Remember: the bucket sort must be stable, meaning it must not mix up the order of “equivalent” elements. This is imperative for a radix sort to work properly.
For a binary bucket sort over a linked list, life is pretty simple — only two buckets are necessary, and you only need keep track of the last node in each bucket to append.
If you are using a doubly-linked list that bookkeeping is done for you. If you are using a singly-linked list you will have to do it manually.
Node heads[2] = { Node{}, Node{} };
Node * tails[2] = { &heads[0], &heads[1] };
while (head)
{
int bucket = value_to_bucket_fn( head->data );
tails[bucket]->next = head; // append current head to correct bucket
tails[bucket] = head; // bucket’s new tail is the current head
head = head->next; // pop current head; get new current head
}
Hopefully you can see how easy this would be to expand to any number of buckets. Still, we will stick with two.
Once you have split all the nodes into the two buckets, just join them back together into your new complete list. Don’t forget to clean up the tail’s next pointer!
head = heads[0]->next;
tails[0]->next = heads[1]->next;
tails[1]->next = nullptr;
Be sure to check out trincot’s answer to see how he defined his singly-linked list with a lastNode pointer and useful functions to make all this splitting into buckets (“partitions”) and joining the final list into invocations of very inexpensive member functions.
Generics
This answer spends some time going on about keys and non-integer values. I have defined my list type’s nodes as:
struct node_type
{
T data;
node_type * next;
};
And I have defined the sorting functions as:
template <typename ValueToBucket>
void binary_bucket_sort( ValueToBucket value_to_bucket );
template <typename ValueToKey>
void radix_sort( ValueToKey value_to_key );
Then, when I sorted my test lists, I used variations of:
list <int> xs;
...
xs.radix_sort( []( int x ) { return x; } );
You can do things like observe the stability in the sort by playing with the value→key function (lambda). For example, I could define a list of integers where the one’s digit didn’t matter:
xs.radix_sort( []( int x ) { return x / 10; } );
Or a list of floats where the fractional part only mattered to two decimal places:
xs.radix_sort( []( double x ) { return static_cast <long long> ( x * 100 ); } );
I could have a list of Student where I am only interested in sorting by the student’s ID:
xs.radix_sort( []( const Student & student ) { return student.ID; } );
As long as the value→key function returns a sufficiently unique integer value we can use radix sort.
The main problem in your approach is that the only thing that can happen with a node is that it eventually gets moved to the start of the list. But there is nothing else that can happen with a node. For instance, there is no logic that leaves a node where it is and then moves on to the next. Instead the code keeps looking at the same node until it can be moved. It should be clear that this cannot result in a sorted order.
Secondly, if you are using radix 10, you will need 10 different possible destinations for a node ("buckets"), depending on the digit that is inspected. These would be linked lists as well, but you need to somehow manage them. Then when all nodes have been distributed over this buckets, the buckets should be joined again into a single list.
I would suggest using radix 2. Then you only need two "buckets". Also, I would suggest to keep track of the last node in a list (if you haven't already done so), with a lastNode member in your class.
Here is an implementation with radix 2 and the use of two bucket linked lists in each pass:
#include <iostream>
#include <vector>
class Node {
public:
Node *next = nullptr;
int data;
Node (int data): data(data) {};
Node (int data, Node *next): data(data), next(next) {};
};
class simpleList {
public:
Node *firstNode = nullptr;
Node *lastNode = nullptr;
simpleList() {}
simpleList(std::vector<int> data) {
for (auto value: data) {
append(value);
}
}
void clear() { // Does not free nodes
firstNode = lastNode = nullptr;
}
// Three variants of append. To append:
// * A node
// * A value, for which a Node will be created
// * Another linked list, which will be emptied
void append(Node *node) {
if (!firstNode) {
firstNode = node;
} else {
lastNode->next = node;
}
lastNode = node;
node->next = nullptr;
}
void append(int data) {
append(new Node(data));
}
void append(simpleList *other) {
if (firstNode) {
lastNode->next = other->firstNode;
} else {
firstNode = other->firstNode;
}
if (other->firstNode) {
lastNode = other->lastNode;
other->clear();
}
}
Node *popFirstNode() {
auto node = firstNode;
if (firstNode) {
firstNode = firstNode->next;
if (!firstNode) {
lastNode = nullptr;
}
node->next = nullptr;
}
return node;
}
void print() {
auto node = firstNode;
while (node) {
std::cout << node->data << " ";
node = node->next;
}
std::cout << "\n";
}
void radixSort() {
bool hasMoreBits = true;
simpleList *partitions[] = {new simpleList(), new simpleList()};
for (int bit = 0; hasMoreBits; bit++) {
hasMoreBits = false;
while (firstNode) {
hasMoreBits |= ((firstNode->data >> bit) >> 1) != 0;
int digit = (firstNode->data >> bit) & 1;
partitions[digit]->append(popFirstNode());
}
append(partitions[0]);
append(partitions[1]);
}
}
};
// Demo
int main() {
auto list = new simpleList({4, 9, 1, 2, 6, 8, 3, 7, 5});
list->print();
list->radixSort();
list->print();
}
Example of a base 256 (8 bit) radix sort for linked list using 64 bit unsigned integers for data. The list structure used in the code uses a pointer to pointer for the tail to simplify the code. A base 256 (8 bit, 8 sort passes) is about 8 times as fast as a base 2 (single bit, 64 sort passes) radix sort.
typedef struct NODE_{ // node struct
struct NODE_ * next;
uint64_t data;
}NODE;
typedef struct LIST_{ // list struct
NODE * phead;
NODE ** pptail;
}LIST;
NODE * RadixSort(NODE * plist)
{
LIST alist[256]; // array of lists
NODE *pnode = plist;
uint32_t i, j, k;
size_t x;
for(k = 0; k < 64; k += 8){ // radix sort
for (i = 0; i < 256; i++) { // reset alist
alist[i].phead = 0;
alist[i].pptail = &alist[i].phead;
}
pnode = plist; // split into lists
while(pnode){
x = ((pnode->data) >> k) & 0xff;
*(alist[x].pptail) = pnode;
alist[x].pptail = &(pnode->next);
pnode = pnode->next;
}
// // concatenate lists
for(i = 0; alist[i].phead == 0; i++);
plist = alist[i].phead;
j = i;
for(++i; i < 256; ++i){
if(alist[i].phead == 0)
continue;
*(alist[j].pptail) = alist[i].phead;
j = i;
}
*(alist[j].pptail) = 0;
}
return plist;
};

Left View Of a Binary Tree

To find set of all nodes that are visible from left side of binary tree.
vector<int> getLeftView(TreeNode<int> *root)
{
static vector<int> res;
// Your code here
if(root){
res.push_back(root->data);
if(root->left)
getLeftView(root->left);
else
getLeftView(root->right);
}
return res;
}
For a single test case at a time it works fine. But when multiple test cases are run, the previous values in the vector is appended by the new values. How do I clear the vector before running the next test case?
You used static because you need a single instance of the vector to be used across the recursion. But static is not the way; it causes there to be just one instance of the vector in the entire program as such.
There are various solutions, one of which is to split the function into the API and recursive part:
void getLeftViewRec(TreeNode<int> *root, vector<int> &res)
{
if(root){
res.push_back(root->data);
if(root->left)
getLeftView(root->left, res);
else
getLeftView(root->right, res);
}
return res;
}
vector<int> getLeftView(TreeNode<int> *root)
{
vector<int> res;
getLeftViewRec(root, res);
return res;
}
Now what happens is that every time getLeftView is called, a new vector res is instantiated as a local variable. It then calls the recursive function getLeftViewRec which receives res by reference, and passes it to itself through the recursive calls, so the recursion is working with a single vector, accumulating into it.
Using queue and a null pointer to mark the first element of each level. we insert a null pointer in the first and as reach that null pointer we mark bool as true and take the next element as our left view element,
// C++ Code for the above iterative approach
#include <bits/stdc++.h>
using namespace std;
// Tree Node Structure contains data, left and right
// pointer
struct Node {
int data;
struct Node *left, *right;
};
// A utility function to
// create a new Binary Tree Node
struct Node* newNode(int item)
{
struct Node* temp
= (struct Node*)malloc(sizeof(struct Node));
temp->data = item;
temp->left = temp->right = NULL;
return temp;
}
// function to get the left view of binary tree in vector
vector<int> leftView(Node* root)
{
// store the left view
vector<int> ans;
// Base Case : Empty Tree
if (!root)
return ans;
// Create an empty queue and enque root node and null
queue<Node*> q;
q.push(root);
q.push(NULL);
bool ok = true;
// Traverse till queue is not empty
while (!q.empty()) {
// get the front node and dequeue it from queue
auto it = q.front();
q.pop();
// if the front node is null do following steps
if (it == NULL) {
if (ok == false)
ok = true;
if (q.size() == 0)
break;
else
q.push(NULL);
}
// else do the following steps
else {
if (ok) {
ans.push_back(it->data);
ok = false;
}
if (it->left)
q.push(it->left);
if (it->right)
q.push(it->right);
}
}
// return the left view
return ans;
}
// driver code to test above code on a test case
int main()
{
/*
Input :
10
/ \
2 3
/ \ / \
7 8 12 15
/
14
Output : 10 2 7 14
*/
// let's build above shown tree
Node* root = newNode(10);
root->left = newNode(2);
root->right = newNode(3);
root->left->left = newNode(7);
root->left->right = newNode(8);
root->right->right = newNode(15);
root->right->left = newNode(12);
root->right->right->left = newNode(14);
// call leftview function and store output in vec
vector<int> vec = leftView(root);
// traverse on left view and print each element
for (int x : vec)
cout << x << " ";
cout << endl;
return 0;
}

Why is there a memory error in this adjacency list?

In the code, I create an adjacency list with an array and each element of the array makes a list with it's adjacent nodes.
To access the array I needed to use ints; however, my vertex names were strings, so I mapped each vertex name to an int counting up from 0. As you can see in the nextNode() function the when a new node is created the'next'node should always be null.
An example result of the adjacency list will look something like this
inputVertices: a,b,c,d
inputEdges: (a,b), (a,d), (b,c) (d,b)
mapping: a<->0, b<->1, c<->2, d<->3
adjacency list:
arr elements| linked lists connected to elements
0 |->b->d
1 |->c
2 |
3 |->b
struct Node {
string vert;
int weight;
Node *next;
};
struct List {
struct Node *head;
};
class Graph {
int vertices;
int edges;
struct List *vertexArray;
int count = 0;
map<string, int> vertList;
public:
Graph(int vertices) {
this->vertices = vertices;
vertexArray = new List[vertices];
for (int i = 0; i < vertices; i++) {
vertexArray[i].head = NULL;
}
}
~Graph() {
vertList.clear();
}
Node *nextNode(string vert) {
Node *newNode = new Node;
newNode->vert = vert;
newNode->weight = 0;
newNode->next = NULL;
return newNode;
}
void addVertex(string vert) {
vertList[vert] = count; //maps Vertex to an integer in the order the Vertex is added
count++;
}
void addEdge(string head, string vert, int weight) {
Node *newNode = nextNode(vert);
newNode->weight = weight;
newNode->next = vertexArray[vertList.at(head)].head;
vertexArray[vertList.at(head)].head = newNode;
}
I stumbled upon my problem while trying to print my adjacency list
here and the program always crashes in the while loop below. It gets
through the first list of nodes fine, but crashes during the second
list.
I figured out the reason is the first list points to everything fine array[0].head->next = node1 node1->next = node2...noden->next = null(this exits the loop), however for the second list something different happens: array[1].head->next = node1 node1->next = node2...noden->next = 0xabababab. The last node should be null, but it is not. I set all new nodes to null. This causes a seg fault and crashes the program.
void print() {
for (int i = 0; i < vertices; i++) {
Node *n = vertexArray[i].head;
for (auto it = vertList.cbegin(); it != vertList.cend(); ++it) {
if ((*it).second == i) { // true if second type in map (aka int) == current array position
cout << (*it).first; //corresponding first type in map
while (n) {
cout << "-> " << n->vert;
n = n->next;
}
cout << endl;
}
}
}
}

Displaying shortest path via bfs search in directed graph

I've been working on a project for college and ran into a rather large problem. I'm supposed to make a function that gets the shortest path through a directed graph from point A to point B and display the path in order.
EX. if the node holds a state name and we want to find the shortest path between California and Utah the output would show california -> nevada -> utah
Currently, my traversal shows all nodes searched with bfs instead of the list of nodes that we took to get from point A to point B.
Below is my implementation of the assignment. My only real question is how would I go about keeping track of the nodes I actually traversed instead of all nodes searched.
bool DirectedGraph::GetShortestPath(
const string& startNode, const string& endNode,
bool nodeDataInsteadOfName, vector<string>& traversalList) const
{
//Nodes are the same
if (startNode.compare(endNode) == 0)
return false;
//Stores the location of our nodes in the node list
vector<int> path;
//Queue to hold the index of the node traversed
queue<int> q;
//Create our boolean table to handle visited nodes
bool *visited = new bool[m_nodes.size()];
//initialize bool table
memset(visited, false, sizeof(bool) * m_nodes.size());
//Label the start node as visited
visited[GetNodeIndex(startNode)] = true;
//Push the node onto our queue
q.push(GetNodeIndex(startNode));
while (!q.empty())
{
//Store the nodes index
int index = q.front();
path.push_back(q.front());
q.pop();
int i = 0;
for (i = 0; i < m_nodes[index]->Out.size(); i++)
{
//If this node matches what we are looking for break/return values
if (m_nodes[index]->Out[i]->targetI == GetNodeIndex(endNode))
{
path.push_back(m_nodes[index]->Out[i]->targetI);
if (nodeDataInsteadOfName)
{
path.push_back(m_nodes[index]->Out[i]->targetI);
for (int x = 0; x < path.size(); x++)
{
traversalList.push_back(m_nodes[path[x]]->Data);
}
}
else
{
for (int x = 0; x < path.size(); x++)
{
traversalList.push_back( m_nodes[path[x]]->Name);
}
}
return true;
}
//Continue through the data
if (!visited[m_nodes[index]->Out[i]->targetI])
{
visited[m_nodes[index]->Out[i]->targetI] = true;
q.push(m_nodes[index]->Out[i]->targetI);
}
}
}
// You must implement this function
return false;
}
//definition of graph private members
struct Edge
{
int srcI; // Index of source node
int targetI; // Index of target node
Edge(int sourceNodeIndex, int targetNodeIndex)
{
srcI = sourceNodeIndex;
targetI = targetNodeIndex;
}
};
struct Node
{
string Name;
string Data;
Node(const string& nodeName, const string& nodeData)
{
Name = nodeName;
Data = nodeData;
}
// List of incoming edges to this node
vector<Edge*> In;
// List of edges going out from this node
vector<Edge*> Out;
};
// We need a list of nodes and edges
vector<Node*> m_nodes;
vector<Edge*> m_edges;
// Used for efficiency purposes so that quick node lookups can be
// done based on node names. Maps a node name string to the index
// of the node within the nodes list (m_nodes).
unordered_map<string, int> m_nodeMap;
The first problem is with the if inside the for loop. Your path variable can only contain two items: the starting and the ending nodes. I suggest you do no track the path with the for loop. Instead, assign each node a distance.
struct Node
{
string Name;
string Data;
int Distance;
Node(const string& nodeName, const string& nodeData)
{
Name = nodeName;
Data = nodeData;
Distance = INT_MAX;
}
// List of incoming edges to this node
vector<Edge*> In;
// List of edges going out from this node
vector<Edge*> Out;
};
and set the distance of the starting node to zero, before looping.
m_nodes[GetNodeIndex(startNode)]->Distance = 0;
At each iteration, pick a node from the queue (you called it index), loop through its adjacency list (outgoing arcs) and test if the adjacent node is visited. If the node is visited, skip it. If the node is not visited, visit it by setting its distance to
m_nodes[index]->Distance + 1
After updating the distance of each node, check if it is the final node, if so break out of the loops.
At this point you have the distance's updated properly. Work your way from the end node backwards, each time selecting the node from the adjacency list with (distance = current node's distance - 1). You can do this using m_edges vector, each time you actually know targetI, so you can check for its corresponding scrI's with the distance value mentioned above.

Graph Representation using Linked-List

Im having some trouble trying to figure out how to get the pointers right when adding edges to a certain paired vertex.
Below is a short idea about how the linked list should look like after Vertexs and Nodes are done being Inputed.
How can i keep order on the neighborList as well? Should there be another condition if there is already a vertex edge in that current vertex?
Heres the Structured Class im trying to build:
class graph{
private:
typedef struct node{
char vertex;
node * nodeListPtr;
node * neighborPtr;
}* nodePtr;
nodePtr head;
nodePtr curr;
public:
graph();
~graph();
void AddNode(char AddData);
void AddEdge(char V, char E);
void printList();
};
graph::graph(){
head = NULL;
curr = NULL;
}
// Adds a node to a linked list
void graph::AddNode(char AddData){
nodePtr n = new node;
n->nodeListPtr = NULL;
n->vertex = AddData;
if(head != NULL){
curr = head;
while(curr->nodeListPtr != NULL){
curr = curr->nodeListPtr;
}
curr->nodeListPtr = n;
}
else{
head = n;
}
}
// takes 2 Parameters (V is pointing to E)
// I want to set it up where the neighborptr starts a double linked List basically
void graph::AddEdge(char V, char E){
// New Node with data
nodePtr n = new node;
n->neighborPtr = NULL;
n->vertex = E;
// go to the first node in the nodeList and go through till you reach the Vertex V
curr = head;
while(curr->vertex != V){
curr = curr->nodeListPtr;
}
//Once the Vertex V is found in the linked list add the node to the neighborPtr.
curr->neighborPtr = n;
}
One problem you currently have is that each node can only have one "edge" node. In your illustration, nodes A, C, and D are all possible, but node B is not without doing things a little differently.
The problem happens here:
curr->neighborPtr = n;
Every time you call AddEdge() to the same vertex, it will simply overwrite that vertex's neighborPtr. You make no effort to traverse the neighborPtrs until you find a null pointer.
Consider adding another while loop for adding edges recursively:
while (curr->neighborPtr != null)
curr = curr->neighborPtr;
curr->neighborPtr = n;
Note that this is not the only issue in your code; you have a few places where you should be guarding against null pointers and are not. For example: in AddEdge(), what happens if the vertex V cannot be found? You are acting under the assumption that it has already been created. If it hasn't, you will end up with some null pointer errors. Keep this in mind if you are trying to make code that is robust in addition to being functional.