I have been trying to do a graph search for a problem from Hackerrank. Lastly, I have come up with
#include <cstdio>
#include <list>
using namespace std;
void bfs(list<int> adjacencyList[], int start, int countVertices) {
// initialize distance[]
int distance[countVertices];
for(int i=0;i < countVertices; i++) {
distance[i] = -1;
}
list<int>::iterator itr;
int lev = 0;
distance[start-1] = lev; // distance for the start vertex is 0
// using start -1 since distance is array which are 0-indexed
list<int> VertexQueue;
VertexQueue.push_back(start);
while(!VertexQueue.empty()) {
int neighbour = VertexQueue.front();
itr = adjacencyList[neighbour].begin();
while(itr != adjacencyList[neighbour].end()) {
int vertexInd = (*itr) - 1;
if(distance[vertexInd] == -1) { // a distance of -1 implies that the vertex is unexplored
distance[vertexInd] = (lev + 1) * 6;
VertexQueue.push_back(*itr);
}
itr++;
}
VertexQueue.pop_front();
lev++;
}
// print the result
for(int k=0;k< countVertices;k++) {
if (k==start-1) continue; // skip the start node
printf("%d ",distance[k]);
}
}
int main() {
int countVertices,countEdges,start,T,v1,v2;
scanf("%d", &T);
for(int i=0; i<T; i++) {
scanf("%d%d", &countVertices,&countEdges);
list<int> adjacencyList[countVertices];
// input edges in graph
for(int j=0; j<countEdges; j++) {
scanf("%d%d",&v1,&v2);
adjacencyList[v1].push_back(v2);
adjacencyList[v2].push_back(v1); // since the graph is undirected
}
scanf("%d",&start);
bfs(adjacencyList, start, countVertices);
printf("\n");
}
return 0;
}
However, this is resulting in 'Segmentation Fault' and I cannot figure out where I am going wrong.
Also, I have comes across segmentation fault a lot of times, but have no idea how to debug it. Would be great if someone can give me an idea of that.
scanf("%d%d", &countVertices,&countEdges);
list<int> adjacencyList[countVertices];
Above code appears wrong. If your indices start with 1, either make adjacencyList of size countVertices + 1 or decrease u and v before putting them in the list.
You can also use a (an unordered) map mapping vertex to a list which will not segfault.
Also not that VLA are not part of standard C++, so avoid them even if your compiler support them as extension.
Related
TLE code completes at 2.1 secs. I'm also passing many things through reference but it's still throwing a TLE. Why this code takes so much time?
here is the problem at hackerearth:
https://www.hackerearth.com/problem/algorithm/falling-dominos-49b1ed46/
Dominos are lots of fun. Children like to stand the tiles on their side in long lines. When one domino falls, it knocks down the next one, which knocks down the one after that, all the way down the line. However, sometimes a domino fails to knock the next one down. In that case, we have to knock it down by hand to get the dominos falling again. Your task is to determine, given the layout of some domino tiles, the minimum number of dominos that must be knocked down by hand in order for all of the dominos to fall.
Input
The first line of input contains one integer specifying the number of test cases to follow. Each test case begins with a line containing two integers, each no larger than 100 000. The first integer n is the number of domino tiles and the second integer m is the number of lines to follow in the test case. The domino tiles are numbered from 1 to n. Each of the following lines contains two integers x and y indicating that if domino number x falls, it will cause domino number y to fall as well.
Output
For each test case, output a line containing one integer, the minimum number of dominos that must be knocked over by hand in order for all the dominos to fall.
SAMPLE INPUT
1
3 2
1 2
2 3
SAMPLE OUTPUT
1
code completes at 2.1
#include <iostream>
#include <vector>
#include <unordered_set>
#include <stack>
using namespace std;
void dfs(const vector<vector<int>> &edges, unordered_set<int> &visited,int sv, stack<int> &stk){
visited.insert(sv);
for(int i=0;i<edges[sv].size();i++){
int current = edges[sv][i];
if(visited.find(current)==visited.end())
dfs(edges, visited, current, stk);
}
stk.push(sv);
}
void dfs(const vector<vector<int>> &edges, unordered_set<int> &visited,int sv){
visited.insert(sv);
for(int i=0;i<edges[sv].size();i++){
int current = edges[sv][i];
if(visited.find(current)==visited.end())
dfs(edges, visited, current);
}
}
int main()
{
int t;
cin>>t;
while(t--){
int V, E;
cin>>V>>E;
vector<vector<int>> edges(V+1);
unordered_set<int> visited;
stack<int> stk;
while(E--){
int f, s;
cin>>f>>s;
edges[f].push_back(s);
}
for(int i=1;i<=V;i++)
if(visited.find(i)==visited.end())
dfs(edges, visited, i, stk);
visited.clear();
int count{0};
while(!stk.empty()){
int current = stk.top();
stk.pop();
if(visited.find(current)==visited.end()){
dfs(edges, visited, current);
count++;
}
}
cout<<count<<endl;
}
return 0;
}
Efficient Code completes at 0.7 sec.
#include<iostream>
#include<bits/stdc++.h>
using namespace std;
void dfs( vector<int> *edges , int start,int n,bool *visit ,stack<int> *nodex)
{
visit[start] = true;
// cout<<start<<endl;
for (int i = 0; i < edges[start].size(); ++i)
{
int next = edges[start][i];
if(visit[next] == false)
dfs(edges,next,n,visit,nodex);
}
nodex->push(start);
}
void dfs(vector<int> *edges,int start, bool *visit,int n)
{
visit[start] = true;
for(int i=0;i<edges[start].size();i++)
{
int next = edges[start][i];
if(visit[next]==false)
dfs(edges,next,visit,n);
}
}
int main()
{
int t;
cin>>t;
while(t--)
{
int n,m;
cin>>n>>m;
vector<int> *edges = new vector<int>[n+1];
for (int i = 0; i < m; ++i)
{
int start,end;
cin>>start>>end;
edges[start].push_back(end);
}
// cout<<"PHASE 1"<<endl;
bool *visit = new bool[n+1];
for (int i = 0; i<=n; ++i)
{
visit[i] = false;
}
stack<int> *nodex = new stack<int>();
for (int i = 1; i<=n; ++i)
{
if(visit[i] == false)
dfs(edges,i,n,visit,nodex);
}
// cout<<"PHASE 2"<<endl;
for(int i=0;i<=n;i++)
visit[i] = false;
int count=0;
while(!nodex->empty())
{
int up = nodex->top();
nodex->pop();
// cout<<" EVERYTHING ISS FINE "<<up<<endl;
if(visit[up] ==false )
{
dfs(edges,up,visit,n);
count++;
}
// cout<<"Everrything is fine "<<up<<endl;
}
cout<<count<<endl;
}
return 0;
}
Use Fast I/O and "\n"in place of endl. This helps a lot in getting rid of TLE. For me the rest of the code seems to be fine
I am implementing bfs (Breadth First Search ) for the graph , but I am getting an error while I pass the starting value of the vector to an integer, for the dfs function to perform, as in the dfs function I have passed the source of the vector, i.e the first element of the vector.
error is on the line where start is declared to v[i]
Here is the complete code
#include <iostream>
#include <vector>
#include <queue>
#include <stdio.h>
using namespace std;
vector<int> v[10];
bool visited[10];
int level[10];
int a = 0;
int arr[10];
void dfs(int s) //function should run only one time
{
queue<int> q;
q.push(s);
visited[s] = true;
level[s] = 0;
while (!q.empty())
{
int p = q.front();
arr[a] = p;
a++;
q.pop();
for (int i = 0; i < v[p].size(); i++)
{
if (visited[v[p][i]] == false) {
level[v[p][i]] = level[p] + 1;
q.push(v[p][i]);
visited[v[p][i]] = true;
}
}
}
}
int main()
{
char c;
int start; // starting element of the vector
int i = 0; // for keeping track of the parent
int countt = 0; // keep track of the no of parents
bool check;
printf("Child or Parent ?");
scanf("%c", &c);
while (countt <= 10) {
if (c == 'c') {
check = true;
int j = 0;
while (check) {
// to keep the track of the child;
scanf("%d", &v[i][j]);
j++;
}
}
if (c == 'p')
{
scanf("%d", &v[i]);
if (i == 0)
{
start = v[i];
}
i++;
countt++;
}
}
printf(" Vector input completed");
dfs(start);
printf("DFS completed, printing the dfs now ");
for (int g = 0; g <= 10; g++)
{
printf("%d", &arr[g]);
}
}
In your current code, v is an array of size 10 containing vector's. However, start is an int, so there is nothing strange in getting an error when trying to assign one to another.
I believe that you wanted v to be either an array of ints or vector of ints. In such a case you just have to declare v properly: int v[10] or vector<int> v(10).
This is general syntax: if you want to declare a vector with known size then you have to put it in (), not in []. Note that you can also fill the vector with some initial values (say zeroes) by writing vector<int> v(10, 0).
In case got you wrong and you wanted to store a graph as vector of vectors, then you can write vector<vector<int>> v(10).
I am making a program to identify whether a 5 card ( user input ) array is a certain hand value. Pair, two pair, three of a kind, straight, full house, four of a kind ( all card values are ranked 2-9, no face cards, no suit ). I am trying to do this without sorting the array. I am currently using this to look through the array and identify if two elements are equal to each other
bool pair(const int array[])
{
for (int i = 0; i < array; i++)
{
if (array[i]==aray[i+1])
{
return true;
}
else
return false;
}
Does this section of code only evaluate whether the first two elements are the same, or will it return true if any two elements are the same? I.E if the hand entered were 2,3,2,4,5 would this return false, where 2,2,3,4,5 would return true? If so, how do I see if any two elements are equal, regardless of order, without sorting the array?
edit: please forgive the typos, I'm leaving the original post intact, so as not to create confusion.
I was not trying to compile the code, for the record.
It will do neither:
i < array will not work, array is an array not an int. You need something like int arraySize as a second argument to the function.
Even if you fix that then this; array[i]==aray[i+1] will cause undefined behaviour because you will access 1 past the end of the array. Use the for loop condition i < arraySize - 1.
If you fix both of those things then what you are checking is if 2 consecutive cards are equal which will only work if the array is sorted.
If you really cant sort the array (which would be so easy with std::sort) then you can do this:
const int NumCards = 9; // If this is a constant, this definition should occur somewhere.
bool hasPair(const int array[], const int arraySize) {
int possibleCards[NumCards] = {0}; // Initialize an array to represent the cards. Set
// the array elements to 0.
// Iterate over all of the cards in your hand.
for (int i = 0; i < arraySize; i++) {
int myCurrentCard = array[i]; // Get the current card number.
// Increment it in the array.
possibleCards[myCurrentCard] = possibleCards[myCurrentCard] + 1;
// Or the equivalent to the above in a single line.
possibleCards[array[i]]++; // Increment the card so that you
// count how many of each card is in your hand.
}
for (int i = 0; i < NumCards; ++i) {
// If you want to check for a pair or above.
if (possibleCards[i] >= 2) { return true; }
// If you want to check for exactly a pair.
if (possibleCards[i] == 2) { return true; }
}
return false;
}
This algorithm is actually called the Bucket Sort and is really still sorting the array, its just not doing it in place.
do you know the meaning of return keyword? return means reaching the end of function, so in your code if two adjacent values are equal it immediately exits the function; if you want to continue checking for other equality possibilities then don't use return but you can store indexes of equal values in an array
#include <iostream>
using namespace std;
int* CheckForPairs(int[], int, int&);
int main()
{
int array[ ]= {2, 5, 5, 7, 7};
int nPairsFound = 0;
int* ptrPairs = CheckForPairs(array, 5, nPairsFound);
for(int i(0); i < nPairsFound; i++)
{
cout << ptrPairs[i] << endl;
}
if(ptrPairs)
{
delete[] ptrPairs;
ptrPairs = NULL;
}
return 0;
}
int* CheckForPairs(int array[] , int size, int& nPairsFound)
{
int *temp = NULL;
nPairsFound = 0;
int j = 0;
for(int i(0); i < size; i++)
{
if(array[i] == array[i + 1])
nPairsFound++;
}
temp = new int[nPairsFound];
for(int i(0); i < size; i++)
{
if(array[i] == array[i + 1])
{
temp[j] = i;
j++;
}
}
return temp;
}
You could use a std::unordered_set for a O(n) solution:
#include <unordered_set>
using namespace std;
bool hasMatchingElements(const int array[], int arraySize) {
unordered_set<int> seen;
for (int i = 0; i < arraySize; i++) {
int t = array[i];
if (seen.count(t)) {
return true;
} else {
seen.insert(t);
}
}
return false;
}
for (int i = 0; i < array; i++)
{
if (array[i]==aray[i+1])
{
return true;
}
else
return false;
This loop will only compare two adjacent values so the loop will return false for array[] = {2,3,2,4,5}.
You need a nested for loop:
#include <stdio.h>
#include <stdbool.h>
int main()
{
int unsortedArray[] = {2,3,2,4,5};
int size = 5;
for(int i=0;i<size-1;i++)
{ for(int j=i+1;j<size;j++)
{ if(unsortedArray[i]==unsortedArray[j])
{ printf("matching cards found\n");
return 0;
}
}
}
printf("matching cards not found\n");
return 0;
}
----EDIT------
Like Ben said, I should mention the function above will only find the first instance of 2 matching cards but it can't count how many cards match or if there are different cards matching. You could do something like below to count all the number of matching cards in the unsortedArray and save those values into a separate array. It's messier than the implementation above:
#include <iostream>
#include <stdio.h>
#include <stdbool.h>
#defin NUM_CARDS 52;
using namespace std;
int main()
{
int T;
cin>>T;
while(T--)
{
int N,i,j;
cin>>N;
int unsortedArray[N];
for(int i=0;i<N;i++)
cin>>unsortedArray[i];
int count[NUM_CARDS]={0};
int cnt = 0;
for( i=0;i<N-1;i++)
{
for( j=i+1;j<N;j++)
{ if(unsortedArray[i]==-1)
break;
if(unsortedArray[i]==unsortedArray[j])
{
unsortedArray[j]=-1;
cnt++;
}
}
if(unsortedArray[i]!=-1)
{
count[unsortedArray[i]]=cnt; //in case you need to store the number of each cards to
// determine the poker hand.
if(cnt==1)
cout<<" 2 matching cards of "<<unsortedArray[i]<<" was found"<<endl;
else if(cnt>=2)
cout<<" more than 2 matching cards of "<<unsortedArray[i]<<" was found"<<endl;
else
cout<<" no matching cards of "<<unsortedArray[i]<<" was found"<<endl;
cnt = 0;
}
}
We have a problem here, we're trying to find all the shortest paths in graph from one node to another. We have already implemented dijkstra but we really dont know how to find them all.
Do we have to use BFS?
#include <vector>
#include <iostream>
#include <queue>
using namespace std;
typedef pair <int, int> dist_node;
typedef pair <int, int> edge;
const int MAXN = 10000;
const int INF = 1 << 30;
vector <edge> g[MAXN];
int d[MAXN];
int p[MAXN];
int dijkstra(int s, int n,int t){
for (int i = 0; i <= n; ++i){
d[i] = INF; p[i] = -1;
}
priority_queue < dist_node, vector <dist_node>,greater<dist_node> > q;
d[s] = 0;
q.push(dist_node(0, s));
while (!q.empty()){
int dist = q.top().first;
int cur = q.top().second;
q.pop();
if (dist > d[cur]) continue;
for (int i = 0; i < g[cur].size(); ++i){
int next = g[cur][i].first;
int w_extra = g[cur][i].second;
if (d[cur] + w_extra < d[next]){
d[next] = d[cur] + w_extra;
p[next] = cur;
q.push(dist_node(d[next], next));
}
}
}
return d[t];
}
vector <int> findpath (int t){
vector <int> path;
int cur=t;
while(cur != -1){
path.push_back(cur);
cur = p[cur];
}
reverse(path.begin(), path.end());
return path;
}
This is our code, we believe we have to modify it but we really don't know where.
Currently, you are only saving/retrieving one of the shortest paths that you happen to find. Consider this example:
4 nodes
0 -> 1
0 -> 2
1 -> 3
2 -> 3
It becomes clear that you cannot have a single p[] value for each position, as in fact the 4th node (3) has 2 previous valid nodes: 1 and 2.
You could thus replace it with a vector<int> p[MAXN]; and work as follows:
if (d[cur] + w_extra < d[next]){
d[next] = d[cur] + w_extra;
p[next].clear();
p[next].push_back(cur);
q.push(dist_node(d[next], next));
}
else if(d[cur] + w_extra == d[next]){
p[next].push_back(cur); // a new shortest way of hitting this same node
}
You will also need to update your findpath() function as it will need to deal with "branches" resulting in several multiple paths, possibly an exponentially huge amount of paths depending on the graph. If you just need to print the paths, you could do something like this:
int answer[MAXN];
void findpath (int t, int depth){
if(t == -1){ // we reached the initial node of one shortest path
for(int i = depth-1; i >= 0; --i){
printf("%d ", answer[i]);
}
printf("%d\n", last_node); // the target end node of the search
return;
}
for(int i = p[t].size()-1; i >= 0; --i){
answer[depth] = p[t][i];
findpath(p[t][i], depth+1);
}
}
Note you'll need to do p[s].push_back(-1) at the beginning of your dijkstra, besides clearing this vector array between cases.
For example suppose there are 3 nodes A,B,C and A links to B and C, B links to A and C, and C links to B and A. In visual form its like this
C <- A -> B //A links to B & C
A <- B -> C //B links to A & C
B <- C -> A //C links to B & A
Assume the A,B,C are held in an array like so [A,B,C] with index starting at 0. How can I efficiently sort the array [A,B,C] according to the value held by each node.
For example if A holds 4, B holds -2 and C holds -1, then sortGraph([A,B,C]) should return [B,C,A]. Hope its clear. Would it be possible if I can somehow utilize std::sort?
EDIT: Not basic sort algorithm. Let me clarify a bit more. Assume I have a list of Nodes [n0,n1...nm]. Each ni has a left and right neighbor index. For example, n1 left neight is n0 and its right neighbor is n2. I use index to represent the neighbor. If n1 is at index 1, then its left neighbor is at index 0 and its right neighbor is at index 2. If I sort the array, then I need to update the neighbor index as well. I don't want to really implement my own sorting algorithm, any advice on how to proceed?
If I understand the edited question correctly your graph is a circular linked list: each node points to the previous and next nodes, and the "last" node points to the "first" node as its next node.
There's nothing particularly special you need to do the sort that you want. Here are the basic steps I'd use.
Put all the nodes into an array.
Sort the array using any sorting algorithm (e.g. qsort).
Loop through the result and reset the prev/next pointers for each node, taking into account the special cases for the first and last node.
Here is a C++ implementation, hope is useful (it includes several algorithms like dijkstra, kruskal, for sorting it uses depth first search, etc...)
Graph.h
#ifndef __GRAPH_H
#define __GRAPH_H
#include <vector>
#include <stack>
#include <set>
typedef struct __edge_t
{
int v0, v1, w;
__edge_t():v0(-1),v1(-1),w(-1){}
__edge_t(int from, int to, int weight):v0(from),v1(to),w(weight){}
} edge_t;
class Graph
{
public:
Graph(void); // construct a graph with no vertex (and thus no edge)
Graph(int n); // construct a graph with n-vertex, but no edge
Graph(const Graph &graph); // deep copy of a graph, avoid if not necessary
public:
// #destructor
virtual ~Graph(void);
public:
inline int getVertexCount(void) const { return this->numV; }
inline int getEdgeCount(void) const { return this->numE; }
public:
// add an edge
// #param: from [in] - starting point of the edge
// #param: to [in] - finishing point of the edge
// #param: weight[in] - edge weight, only allow positive values
void addEdge(int from, int to, int weight=1);
// get all edges
// #param: edgeList[out] - an array with sufficient size to store the edges
void getAllEdges(edge_t edgeList[]);
public:
// topological sort
// #param: vertexList[out] - vertex order
void sort(int vertexList[]);
// dijkstra's shortest path algorithm
// #param: v[in] - starting vertex
// #param: path[out] - an array of <distance, prev> pair for each vertex
void dijkstra(int v, std::pair<int, int> path[]);
// kruskal's minimum spanning tree algorithm
// #param: graph[out] - the minimum spanning tree result
void kruskal(Graph &graph);
// floyd-warshall shortest distance algorithm
// #param: path[out] - a matrix of <distance, next> pair in C-style
void floydWarshall(std::pair<int, int> path[]);
private:
// resursive depth first search
void sort(int v, std::pair<int, int> timestamp[], std::stack<int> &order);
// find which set the vertex is in, used in kruskal
std::set<int>* findSet(int v, std::set<int> vertexSet[], int n);
// union two sets, used in kruskal
void setUnion(std::set<int>* s0, std::set<int>* s1);
// initialize this graph
void init(int n);
// initialize this graph by copying another
void init(const Graph &graph);
private:
int numV, numE; // number of vertices and edges
std::vector< std::pair<int, int> >* adjList; // adjacency list
};
#endif
Graph.cpp
#include "Graph.h"
#include <algorithm>
#include <map>
Graph::Graph()
:numV(0), numE(0), adjList(0)
{
}
Graph::Graph(int n)
:numV(0), numE(0), adjList(0)
{
this->init(n);
}
Graph::Graph(const Graph &graph)
:numV(0), numE(0), adjList(0)
{
this->init(graph);
}
Graph::~Graph()
{
delete[] this->adjList;
}
void Graph::init(int n)
{
if(this->adjList){
delete[] this->adjList;
}
this->numV = n;
this->numE = 0;
this->adjList = new std::vector< std::pair<int, int> >[n];
}
void Graph::init(const Graph &graph)
{
this->init(graph.numV);
for(int i = 0; i < numV; i++){
this->adjList[i] = graph.adjList[i];
}
}
void Graph::addEdge(int from, int to, int weight)
{
if(weight > 0){
this->adjList[from].push_back( std::make_pair(to, weight) );
this->numE++;
}
}
void Graph::getAllEdges(edge_t edgeList[])
{
int k = 0;
for(int i = 0; i < numV; i++){
for(int j = 0; j < this->adjList[i].size(); j++){
// add this edge to edgeList
edgeList[k++] = edge_t(i, this->adjList[i][j].first, this->adjList[i][j].second);
}
}
}
void Graph::sort(int vertexList[])
{
std::pair<int, int>* timestamp = new std::pair<int, int>[this->numV];
std::stack<int> order;
for(int i = 0; i < this->numV; i++){
timestamp[i].first = -1;
timestamp[i].second = -1;
}
for(int v = 0; v < this->numV; v++){
if(timestamp[v].first < 0){
this->sort(v, timestamp, order);
}
}
int i = 0;
while(!order.empty()){
vertexList[i++] = order.top();
order.pop();
}
delete[] timestamp;
return;
}
void Graph::sort(int v, std::pair<int, int> timestamp[], std::stack<int> &order)
{
// discover vertex v
timestamp[v].first = 1;
for(int i = 0; i < this->adjList[v].size(); i++){
int next = this->adjList[v][i].first;
if(timestamp[next].first < 0){
this->sort(next, timestamp, order);
}
}
// finish vertex v
timestamp[v].second = 1;
order.push(v);
return;
}
void Graph::dijkstra(int v, std::pair<int, int> path[])
{
int* q = new int[numV];
int numQ = numV;
for(int i = 0; i < this->numV; i++){
path[i].first = -1; // infinity distance
path[i].second = -1; // no path exists
q[i] = i;
}
// instant reachable to itself
path[v].first = 0;
path[v].second = -1;
while(numQ > 0){
int u = -1; // such node not exists
for(int i = 0; i < numV; i++){
if(q[i] >= 0
&& path[i].first >= 0
&& (u < 0 || path[i].first < path[u].first)){ //
u = i;
}
}
if(u == -1){
// all remaining nodes are unreachible
break;
}
// remove u from Q
q[u] = -1;
numQ--;
for(int i = 0; i < this->adjList[u].size(); i++){
std::pair<int, int>& edge = this->adjList[u][i];
int alt = path[u].first + edge.second;
if(path[edge.first].first < 0 || alt < path[ edge.first ].first){
path[ edge.first ].first = alt;
path[ edge.first ].second = u;
}
}
}
delete[] q;
return;
}
// compare two edges by their weight
bool edgeCmp(edge_t e0, edge_t e1)
{
return e0.w < e1.w;
}
std::set<int>* Graph::findSet(int v, std::set<int> vertexSet[], int n)
{
for(int i = 0; i < n; i++){
if(vertexSet[i].find(v) != vertexSet[i].end()){
return vertexSet+i;
}
}
return 0;
}
void Graph::setUnion(std::set<int>* s0, std::set<int>* s1)
{
if(s1->size() > s0->size()){
std::set<int>* temp = s0;
s0 = s1;
s1 = temp;
}
for(std::set<int>::iterator i = s1->begin(); i != s1->end(); i++){
s0->insert(*i);
}
s1->clear();
return;
}
void Graph::kruskal(Graph &graph)
{
std::vector<edge_t> edgeList;
edgeList.reserve(numE);
for(int i = 0; i < numV; i++){
for(int j = 0; j < this->adjList[i].size(); j++){
// add this edge to edgeList
edgeList.push_back( edge_t(i, this->adjList[i][j].first, this->adjList[i][j].second) );
}
}
// sort the list in ascending order
std::sort(edgeList.begin(), edgeList.end(), edgeCmp);
graph.init(numV);
// create disjoint set of the spanning tree constructed so far
std::set<int>* disjoint = new std::set<int>[this->numV];
for(int i = 0; i < numV; i++){
disjoint[i].insert(i);
}
for(int e = 0; e < edgeList.size(); e++){
// consider edgeList[e]
std::set<int>* s0 = this->findSet(edgeList[e].v0, disjoint, numV);
std::set<int>* s1 = this->findSet(edgeList[e].v1, disjoint, numV);
if(s0 == s1){
// adding this edge will make a cycle
continue;
}
// add this edge to MST
graph.addEdge(edgeList[e].v0, edgeList[e].v1, edgeList[e].w);
// union s0 & s1
this->setUnion(s0, s1);
}
delete[] disjoint;
return;
}
#define IDX(i,j) ((i)*numV+(j))
void Graph::floydWarshall(std::pair<int, int> path[])
{
// initialize
for(int i = 0; i < numV; i++){
for(int j = 0; j < numV; j++){
path[IDX(i,j)].first = -1;
path[IDX(i,j)].second = -1;
}
}
for(int i = 0; i < numV; i++){
for(int j = 0; j < this->adjList[i].size(); j++){
path[IDX(i,this->adjList[i][j].first)].first
= this->adjList[i][j].second;
path[IDX(i,this->adjList[i][j].first)].second
= this->adjList[i][j].first;
}
}
// dynamic programming
for(int k = 0; k < numV; k++){
for(int i = 0; i < numV; i++){
for(int j = 0; j < numV; j++){
if(path[IDX(i,k)].first == -1
|| path[IDX(k,j)].first == -1){
// no path exist from i-to-k or from k-to-j
continue;
}
if(path[IDX(i,j)].first == -1
|| path[IDX(i,j)].first > path[IDX(i,k)].first + path[IDX(k,j)].first){
// there is a shorter path from i-to-k, and from k-to-j
path[IDX(i,j)].first = path[IDX(i,k)].first + path[IDX(k,j)].first;
path[IDX(i,j)].second = k;
}
}
}
}
return;
}
If you are looking for sorting algorithms you should just ask google:
http://en.wikipedia.org/wiki/Sorting_algorithm
My personal favourite is the BogoSort coupled with parallel universe theory. The theory is that if you hook a machine up to the program that can destroy the universe, then if the list isn't sorted after one iteration it will destroy the universe. That way all the parallel universes except the one with the list sorted will be destroyed and you have a sorting algorithm with complexity O(1).
The best ....
Create a struct like this:
template<typename Container, typename Comparison = std::less<typename Container::value_type>>
struct SortHelper
{
Container const* container;
size_t org_index;
SortHelper( Container const* c, size_t index ):container(c), org_index(index) {}
bool operator<( SortHelper other ) const
{
return Comparison()( (*c)[org_index], (*other.c)[other.org_index] );
}
};
This lets you resort things however you want.
Now, make a std::vector<SortHelper<blah>>, sort it, and you now have a vector of instructions of where everything ends up going after you sort it.
Apply these instructions (there are a few ways). An easy way would be to reuse container pointer as a bool. Walk the sorted vector of helpers. Move the first entry to where it should go, moving what you found where it should go to where it should go, and repeat until you loop or the entire array is sorted. As you go, clear the container pointers in your helper struct, and check them to make sure you don't move an entry that has already been moved (this lets you detect loops, for example).
Once a loop has occurred, proceed down the vector looking for the next as-yet-not-in-right-place entry (with a non-null container pointer).