Kruskal's Algorithm in O(n log n) - c++

I'm interested in learning how to run Kruskal's algorithm on O(n log n) in c++. I have implemented the algorithm with a solution that runs on O(n^2), and the code for that is below.
I know that it should be possible to run Kruskal's on O(n log n), but I'm stymied as to how this can be done. I would appreciate any and all tips.
#include <vector>
#include <algorithm>
#include <set>
using namespace std;
//sort by weight
bool sorting (vector<int> i, vector<int> j) {return i[2]<j[2];}
class Submap {
private:
set<int> finder;
public:
Submap(int x) {finder.insert(x);}
Submap(set<int> x) {finder = x;}
set<int> pointreturn() {return finder;}
//function to add new set to current tree
void add(set<int> np) {
finder.insert(np.begin(), np.end());
}
void add(int n) {
finder.insert(n);
}
int size() {return int(finder.size());}
//find function returns true if the value is not found
bool find(int x) {
if (finder.find(x) == finder.end())
return true;
else
return false;
}
};
class Map {
private:
vector<Submap> submaps;
public:
int find(int x) {
int finder = -1;
for(int i = 0; i < int(submaps.size()); i++) {
if(!submaps[i].find(x)) {
finder = i;
break;
}
}
return finder;
}
void newsubmap(int a, int b) {
set<int> nextset;
nextset.insert(a);
nextset.insert(b);
submaps.push_back(Submap(nextset));
}
void addendum(int a, int index) {
submaps[index].add(a);
}
Submap subfind(int i) {return submaps[i];}
void fuse(int index1, int index2) {
submaps[index1].add(submaps[index2].pointreturn());
vector<Submap> nextmaps;
for(int i = 0; i < int(submaps.size()); i++) {
if (i != index2)
nextmaps.push_back(submaps[i]);
}
submaps = nextmaps;
}
int size() {return submaps[0].size();}
};
Map kruskal (vector<vector<int>> &graph, int weight, int junct) {
//sort the graph
sort(graph.begin(), graph.end(), sorting);
Map currmap;
int usedweight = 0;
for(int i=0; i<graph.size(); i++) {
int a = currmap.find(graph[i][0]);
int b = currmap.find(graph[i][1]);
//the boolean expression here is false if both points are already in the same submap
if(a != b || a == -1) {
usedweight += graph[i][2];
//if neither point is in the map so far
if(a == -1 && b == -1) {
currmap.newsubmap(graph[i][0], graph[i][1]);
}
//if one point is in the map so far
else if (a != -1 && b == -1) {
currmap.addendum(graph[i][1], a);
}
else if (a == -1 && b != -1) {
currmap.addendum(graph[i][0], b);
}
//if both points are in the map, but different submaps
else {
currmap.fuse(a, b);
}
}
//if the first set in the map is spanning, the algorithm is done
if(currmap.size() == junct)
break;
}
return (currmap);
}

Related

Finding a cycle path in directed graph

I am making a directed Graph class. I want find if there is any Cycle and update a vector with it's path accordingly. My Function some times work but others add two times the last edge of the path.So i guess it needs to be tydied up.
Example: having a Graph with these paths
0->1, 0->2, 1->2, 2->3, 3->4, 4->0, 4->6, 1->5, 5->6
should set the vector to [0 2 3 4] or anything else valid.
What I have tried:
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
using namespace std;
class Graph {
private:
int V;
list<int> *adj;
bool isCyclicHelp(int v, bool visited[], bool *rs, vector<int> &path) const{
if(visited[v] == false) {
visited[v] = true;
rs[v] = true;
list<int>::iterator i;
for(i=adj[v].begin(); i!=adj[v].end(); i++) {
if(!visited[*i] && isCyclicHelp(*i, visited, rs, path)) {
path.push_back(*i);
return true;
}
else if(rs[*i]) {
return true;
}
}
}
rs[v] = false;
path.pop_back();
return false;
}
public:
Graph(int V) {
this->V = V;
adj = new list<int>[V];
}
~Graph() {
}
void addEdge(int v, int w) {
if(v != w) {
adj[v].push_back(w);
}
}
bool cycle(vector<int> &path) const {
bool *visited = new bool[V];
bool *recStack = new bool[V];
for(int i=0; i<V; i++) {
visited[i] = false;
recStack[i] = false;
}
for(int i=0; i<V; i++) {
path.push_back(i);
if(Graph::isCyclicHelp(i, visited, recStack, path)) {
reverse(path.begin(), path.end());
return true;
}
path.clear();
}
path.clear();
return false;
}
};

Rabin Karp using linear hash

For course I am taking I need to implement the Rabin-Karp string search algorithm, with different hash implementation. First I have done a rolling hash and that works just fine. Problem is when it comes to linear and separate chaining hash. I have made a linear hash header file and for primary hash methods it works Ok, also I have written a Rabin-Karp algorithm that works with other versions of hash. But now I do not know how to put this two together.
Here is what I have written by now
hash.h
#ifndef HASH_H
#define HASH_H
#include <vector>
using namespace std;
template <typename Tip>
class Hash {
struct Element {
int key;
Tip value;
int mark; //0 free, 1 occupied, 2 was occupied
Element(int key = 0, Tip value = Tip(), int mark = 1):key(key),value(value),mark(mark){}
};
int h1(int key) {
return key%capacity;
}
int h2(int key) {
return 2*(key%5) + 1;
}
int capacity;
int no_of_elements;
const double factor_of_full;
vector<Element> Tabel;
public:
Hash():capacity(128),no_of_elements(0),factor_of_full(0.5){
Tabel.resize(capacity);
for(int i=0;i<capacity;i++)
Tabel[i].mark = 0;
}
void Insert(pair<int,Tip> element);
Tip Find(int key);
void Delete(int key);
};
template <typename Tip>
void Hash<Tip>::Insert(pair<int,Tip> element) {
if((double(no_of_elements+1))/capacity>factor_of_full) {
vector<Element> coppy = Tabel;
capacity*=2;
Tabel.resize(capacity);
no_of_elements = 0;
for(int i=0;i<Tabel.size();i++)
Tabel[i].mark = 0;
for(int i=0;i<coppy.size();i++)
if(coppy[i].mark == 1)
Insert({coppy[i].key,coppy[i].value});
}
int index = h1(element.first);
while(Tabel[index].mark == 1)
index = (index + h2(element.first))%capacity;
Tabel[index] = Element(element.first,element.second);
no_of_elements++;
}
template <typename Tip>
Tip Hash<Tip>::Find(int key) {
int index = h1(key);
for(int i=0;i<capacity;i++) {
if(Tabel[index].mark == 0)
break;
if(Tabel[index].mark == 1 && Tabel[index].key == key)
return Tabel[index].value;
else index = (index+h2(key))%capacity;
}
return Tip();
}
template <typename Tip>
void Hash<Tip>::Delete(int key) {
int index = h1(key);
for(int i=0;i<capacity;i++) {
if(Tabel[index].mark == 0)
return;
if(Tabel[index].mark == 1 && Tabel[index].key == key) {
Tabel[index].mark = 2;
no_of_elements--;
}
else index = (index+h2(key))%capacity;
}
return;
}
#endif // HASH_H
Rabin_Karp.cpp
#include <bits/stdc++.h>
#include "hash.h"
using namespace std;
const int P_B= 227;
const int P_M = 1000005;
int rabin_karp(const string& n, const string& find) {
int h1 = Hash(n);
int h2 = 0;
int pow = 1;
for (int i = 0; i < n.size(); i++)
pow = (pow * P_B) % P_M;
for (int i = 0; i < find.size(); i++) {
h2 = h2*P_B + find[i];
h2 %= P_M;
if (i >= n.size()) {
h2 -= pow * find[i-n.size()] % P_M;
if (h2 < 0)
h2 += P_M;
}
if (i >= n.size()-1 && h1 == h2)
return i - (n.size()-1);
}
return -1;
}

C++ recursive solution of NQUEENS problem not working properly

I am trying to solve the famous NQUEENS problem using backtracking in c++ using vectors and class. But it is giving correct result for some cases(for ex. 5) and for remaining(for ex. 4) it is showing "Solutuon doesn't exist".
My code is as follows:
Class declaration for storing rows and columns of queen position.
class position
{
public:
int r,c;
position(int r,int c)
{
this->r=r;
this->c=c;
}
};
The recursive function:
vector<position> positions;
bool solve(int n, int r)
{
if(r==n)
return true;
for (int c = 0; c < n; ++c)
{
bool safe=true;
for(int q=0;q<r;++q)
{
if (positions[q].c == c || positions[q].r - positions[q].c == r - c
|| positions[q].r + positions[q].c == r + c)
{
safe = false;
break;
}
}
if(safe)
{
position p(r,c);
positions.push_back(p);
if(solve(n,r+1))
return true;
}
}
return false;
}
and the driver function is as follows:
int main()
{
int n;
cin>>n;
if(!solve(n,0))
{
cout<<"Solution doesn't exist"<<endl;
return 0;
}
printboard(n);
return 0;
}
Please help me in resolving this.
if(solve(n,r+1))
return true;
else
positions.erase(positions.begin()+positions.size()-1);
If the solution for one cell doesn't exist then erase that cell from possible positions so that it avoids collisions.
Edit:-
Thank You Mr.Bo R for your correction.

Counting the number of comparisons done in Heapsort

I am trying to count the number of comparisons done by heap sorting algorithm.
my code is based on priority queue and I want to know where I should put the counter. here is what I have but when I try to print the counter it shows zero counts, what am I doing wrong? Thank you.
here is the heapbuild function:
#include<iostream>
vector<int> pq_keys;
void buildHeap()
{
int size = pq_keys.size();
int midIdx = (size -2)/2;
while (midIdx >= 0)
{
shiftRight(midIdx, size-1);
--midIdx;
}
and this is the function that does the comparison:
int shiftRight(int low, int high)
{
int root = low;
int counter=0;
while ((root*2)+1 <= high)
{
int leftChild = (root * 2) + 1;
int rightChild = leftChild + 1;
int swapIdx = root;
if (pq_keys[swapIdx] < pq_keys[leftChild])
{
counter++;
cout<<counter;
swapIdx = leftChild;
}
/*If right child exists check if it is less than current root*/
if ((rightChild <= high) && (pq_keys[swapIdx] < pq_keys[rightChild]))
{
counter++;
swapIdx = rightChild;
}
/*Make the biggest element of root, left and right child the root*/
if (swapIdx != root)
{
counter++;
int tmp = pq_keys[root];
pq_keys[root] = pq_keys[swapIdx];
pq_keys[swapIdx] = tmp;
root = swapIdx;
}
else
{
break;
}
}
return counter;
}
You want to increment the counter before you do the comparison. Consider this code, from your shiftRight method:
if (pq_keys[swapIdx] < pq_keys[leftChild])
{
counter++;
cout<<counter;
swapIdx = leftChild;
}
That only increments the counter if the conditional is true. If pq_keys[swpIdx] >= pq_keys[leftChild], then you made the comparison without counting it. You need to change your code to be:
counter++;
if (pq_keys[swapIdx] < pq_keys[leftChild])
{
cout<<counter;
swapIdx = leftChild;
}
You need to do the same thing in the other two places where you count comparisons: increment the counter, then do the comparison.
class LessPredicate
{
size_t callCount_ = 0;
temlate<class T>
bool compare(const T& l, conct T& r)
{
return l < r; // or other logic
}
public:
size_t CallTimes() const { return callCount_; }
temlate<class T>
bool operator() (const T& l, conct T& r)
{
++callCount_;
return compare(l, r);
}
};
int main()
{
LessPredicate less;
...// use it like less(a, b) instead a < b;
auto compareCount = less.CallTimes();
}

How to design sort algorithm based on two indicators?

I have a container (array or vector) and millions of words. I need to sort them in following order s.
The primary sort order should be the number of characters in the word. The secondary sort order should
be lexicographical. I can not use any library such as sort. I want to create the algorithms from scratch. I appreciate if anyone can hit me up with any reference.
So sorting the words:
This is a list of unsorted words
should give:
a is of This list words unsorted
Edit:
I am not allowed to use any STL such as sort
//Following is my final program
//It wi be run with following: args: <inputfile> <outputfile> <timesfile> <ntests>
//timesfile is for storing times and ntests is for number of test
/*
Bernard Grey
10 Wednesday 10 Sep 2014
*/
#include <iostream>
#include <ctime>
#include <algorithm>
#include <fstream>
#include <cctype>
#include <cstdlib>
#include <cstring>
#include <vector>
using namespace std;
//This node contain two type of information both in the vector
//First is vector for hash function. it contains number of repetition of the word
//Second node contain a word for values in my vector and the other field is for future implementation ;)
struct node
{
string val;
int count;
};
//Definition of inner and outer vectors as cintainer of words and hash table
typedef std::vector<node> StringVector;
typedef std::vector<StringVector> StringVector2D;
//Cited at http://stackoverflow.com/questions/8317508/hash-function-for-a-string :In the comment
int HashTable (string word)
{
int seed = 378551;
unsigned long hash = 0;
for(int i = 0; i < word.length(); i++)
{
hash = (hash * seed) + word[i];
}
return hash % 1000000;//Later assign it to number of words
}
//Cite at: http://stackoverflow.com/questions/25726530/how-to-find-an-struct-element-in-a-two-dimention-vector
struct find_word
{
string val;
find_word(string val) : val(val) {}
bool operator () ( const node& m ) const
{
return m.val == val;
}
};
//I could use swap function in vector instead of implementing this function
void swap(StringVector& vec, int i, int j)
{
node tmp = vec[i];
vec[i] = vec[j];
vec[j] = tmp;
}
//To compare string alphabetically order
bool comp(node& i,node& p)
{
int cmp;
if(i.val.compare(p.val)<0)
{
return true;
}
return false;
}
void quickSort(StringVector& aVec, int left, int right);
int partition(StringVector& aVec, int left, int right);
void swap(StringVector& aVec, int left, int right);
void quickSort(StringVector& aVec, int left, int right)
{
if(right>0){
int index = partition(aVec,left,right);
if (left<index-1) {
quickSort(aVec, left, index-1);
}
if (index<right) {
quickSort(aVec, index,right);
}
}
}
int partition(StringVector& aVec, int left, int right)
{
string pivotNode;
pivotNode = aVec[(left+right)/2].val;
while (left<=right) {
while (aVec[left].val.compare(pivotNode)<0) {left++; }
while (aVec[right].val.compare(pivotNode)>0) {right--; }
if (left<=right) {
swap(aVec,left,right);
left++;
right--;
}
}
return left;
}
//Welcome to Maaaain
int main(int argc, char* argv[])
{
/*file reading and preprocessing*/
if(argc != 5)
{
cerr << "usage: " << argv[0] << " infile outfile timesfile ntests" << endl;
}
ifstream fin(argv[1]);
if(fin.fail())
{
cerr << "Error: failed to open file " << argv[1] << " for input" << endl;
exit(EXIT_FAILURE);
}
int ntests = atoi(argv[4]);
//Len of string and max num word
int stringlen, numwords;
get_max_words(fin, stringlen, numwords);
//initial string
string init[numwords];
//Read the file and add it to first array
for(int i=0; i<numwords; i++)
{
string tmp;
fin >> tmp;
int len = tmp.length();
//There is one single ' in the example output file. so I do not want to delete that one :-)
bool pp = true;
//Remove punct from leading and tail
if(len==1)
{
pp=false;
}
//Remove punc
if( ispunct(tmp[0]) && pp)
{
tmp.erase(0,1);
}
//Remove punc
if( ispunct(tmp[len-1]) && pp)
{
tmp.erase(len-1,1);
}
init[i] =tmp;
}
/*
At this point, everything should be in the initial array
The temporary array should be declared but not filled
*/
clockid_t cpu;
timespec start, end;
long time[ntests];
//2 Dimension vector this will called outer vector
StringVector2D twoD;
if(clock_getcpuclockid(0, &cpu) != 0)
{
cerr << "Error: could not get cpu clock" << endl;
exit(EXIT_FAILURE);
}
int rep = 0;
node tmp;
tmp.count = 0;
tmp.val = "";
//Later I need to assign it to number of words * M ... Good for encryption... It is not a security subject
vector<node> first(1000000,tmp);
//This is called inner vector
vector<string> templateVec;
//Last search?
bool last = false;
//Initialize inner map as needed and put it inside the outer vector with no data
for(int f=0;f<(stringlen);f++)
{
StringVector myVec;
twoD.push_back(myVec);
}
for(int i=0; i<ntests; i++)
{
if(clock_gettime(cpu, &start) == -1)
{
cerr << "Error: could not get start time" << endl;
exit(EXIT_FAILURE);
}
//Check if it is last iteration so do not delete data for printing purposeses
if(i == ntests-1)
{
last = true;
}
/*copy from initial array to temporary array*/
//Initialize inner vector with the values. In this point outer vector is filled with inner vector
//&&& inner vector is empty myvec.empty() = true;
//vector at index 0 is for words with one char... vector 1 is for words with two chars and so on...
for(int j=0; j<numwords; j++)
{
int len = init[j].length()-1;
if(len<0)continue;
//Initilize a node to fill up the vector
node currNode;
currNode.val = init[j];
//currNode.count = 0;
int hash = HashTable(init[j]);
//Node already existed
if(first[hash].count != 0){
//Add to its value in hash table
first[hash].count++;
}
else
{
//Activate word first time!
first[hash].count =1;
//I can even not use this because of the hash table but it may help in future improvment!!!
first[hash].val = init[j];
//Add the word to appropriate level in outer string! 1char == [0] --- 2char== [1] so on
twoD[len].push_back(currNode);
}
}
//Sort Alphabetically order
for(int f=0;f<(stringlen);f++)
{
//Eficcient sorting algorithm with no chance of segmentation dump ;)
quickSort(twoD[f],0,twoD[f].size()-1);
}
//Time finished
if(clock_gettime(cpu, &end) == -1)
{
cerr << "Error: could not get end time" << endl;
exit(EXIT_FAILURE);
}
//Delete items from vector if it is not last iteration --- This is not part of sorting algorithm so it is after clock
if(!last)
{
for(int f=0;f<stringlen;f++)
{
twoD[f].clear();
}
twoD.clear();
for(StringVector::iterator it3 = first.begin();it3!=first.end();it3++)
{
it3->val="";
it3->count=0;
}
//Initialize inner map as needed and put it inside the outer vector
for(int f=0;f<(stringlen);f++)
{
StringVector myVec;
twoD.push_back(myVec);
}
}
/*time per trial in nanoseconds*/
time[i] = (end.tv_sec - start.tv_sec)*1000000000 + end.tv_nsec - start.tv_nsec;
}
/*output sorted temporary array*/
int k=0;
int y =0;
int num=0;
ofstream fout(argv[2]);
//Pointer for inner vector
StringVector::iterator it2;
for (StringVector2D::iterator outer = twoD.begin(); outer != twoD.end(); ++outer){
y++;
k=0;
for (it2= outer->begin(); it2!=outer->end(); ++it2){
//Get back data from hash table
int hash = HashTable(it2->val);
//Number of word in other field of the node
int repWord = first[hash].count;
//Print according to that
for(int g=0; g < repWord ;g++){
num++;
//10 char in one line
if(num%10 == 0)
{
fout << it2->val;
fout<<endl;
k++;
}
else
{
fout<< it2->val << " ";
}
}
}
}
//Sort times with STL for god sake....
sort(time,time+ntests);
//print times to the file///
ofstream ftimes(argv[3]);
for(int i=0; i<ntests; i++)
ftimes << time[i] << endl;
}
//Helper function .. nice job
void get_max_words(ifstream& fin, int& wordlen, int& numwords)
{
char c;
int count=0;
wordlen = numwords = 0;
while(fin.good() && fin.get(c) && isspace(c)){;} //skip leading space
while(fin.good())
{
++numwords;
while(fin.good() && !isspace(c))
{
++count;
fin.get(c);
}
if(count > wordlen)
wordlen = count;
count = 0;
while(fin.good() && fin.get(c) && isspace(c)){;} //skip space
}
if(count > wordlen)
wordlen = count;
fin.clear();
fin.seekg(0, ios::beg);
}
You'll primarily need a comparator for your sort routine to sort on:
bool lessThan(const std::string a, const std::string b) {
if (a.length() != b.length())
return a.length() < b.length();
return a < b;
}
There's actually an easy way to implement this in stl. There's a sort method that takes a comparator:
template <class RandomAccessIterator, class Compare>
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
So you can do this:
bool comparator(const string& a, const string& b) {
if (a.length() < b.length())
return true;
if (a.length() == b.length())
return a < b;
return false;
}
sort(words.begin(), words.end(), comparator);
It's about sorting based on multiple keys. I suggest you study some efficient sorting algorithm, say Quick Sort, then change the comparator to adapt the multiple keys.
For any sorting algorithm that is based on comparing, the easiest way to adapt multiple key sorting is to change the comparing criteria, from a single value to multiple values.
If you are not even allowed to use STL, i.e. you are not allowed to use sort in , here is a post you can start with: Sorting an array using multiple sort criteria (QuickSort)
If you are allowed, just write a comparing function which supports the multiple key comparison and plug it in the sort function. You can check this C++ reference for more details.
An illustration (it's just an illustration to point out how you can plug in the compare function):
bool comparator(const string& a, const string& b) {
if (a.length() < b.length())
return true;
if (a.length() > b.length())
return false;
return a < b;
}
void Qsort(string a[],int low,int high)
{
if(low >= high)
{
return;
}
int left = low;
int right = high;
string key = a[(low + high) >> 1];
while(left < right)
{
while(left < right && comparator(a[left], key)) left++;
while(left < right && !comparator(a[right], key)) right--;
if (left < right)
{
swap(a[left], a[right]);
left++; right--;
}
}
if (left == right) left ++;
if (low < right) Qsort(a, low, left - 1);
if (high > left) Qsort(a, right + 1, high);
}
The answer wants a design, so I'll focus on the design of your sorting library, than an implementation
Your sort algorithm can use your custom comparator objects with a member operator() implemented for comparison between two elements.
Your comparator can be a Linked List of comparators and can call the next comparator if the current one gives a tie. You'll have to ensure that there is always a true and false return though. Or implement something that can create a stable_sort if nothing else.
So the first comparator is number of characters and the second comparator is lexicographical..
This idea is then general enough so that if your requirement changes tomorrow. This can then be reused.
This is on the lines of Chain of Responsibility Pattern. You can templat-ize the comparator after you've got the gist.
Ex:
class Chain_Comparator
{
Chain_Comparator* next;
public:
bool operator()( void* a, void* b )
{
if( a_is_less_b(a, b) )
return true;
else if( b_is_less_a(a,b) )
return false;
else if( next )
return next( a, b )
}
virtual bool a_is_less( void* a, void* b) = 0;
virtual bool b_is_less( void* a, void* b) = 0;
};
class Num_Comparator : public Chain_Comparator
{
// Implements a_is_less etc.
};
class Lex_Comparator : public Chain_Comparator
{
// Implement lex comparisons.
};
void your_custom_sorting_method( vector<int > a, Chain_Comparator& c)
{
// Implementation goes here.
// call the operator() for c with simply : c( a[i], a[j] )
}