Kruskal
Kruskal
Implementation
of
Kruskal's Algorithm
A Mini Project
Submitted
In
Partial Fulfillment of the Requirements
For the degree of
Bachelor of Technology
By
Aftab Khan
Gaurav Srivastava
Gaurav Tomar
B.Tech (CS)
5th Semester
(Session: 2009-2010)
December 2009
SHIVDAN SINGH INSTITUTE OF TECHNOLOGY & MANAGEMENT
Approved by AICTE & Affiliated to U.P. Technical University, Lucknow
10 km stone, Aligarh-Mathura Road, P.O. Mahua, Aligarh (U.P)
_____________________________________________________________
Certificate
Date:
Aftab Khan
Gaurav Srivastav
Gaurav Tomar
Table of Content
Team description
• Members
• Team leader
• Work distribution
System requirements
• Hardwares
• Softwares
Kruskal’s algorithm
Introduction
Functional description
• Performance
• Pseudocode/algorithm
• Proof of correctness
• Spanning tree
• Minimality
• Example
Design details
Coding details
Testing plan
Limitation
Source code
References
Team description
Members
Aftab Khan 0600710006
Gaurav Srivastava 0600710033
Gaurav Tomar 07007100
Team Leader
Gaurav Srivastava
Work distribution
The algorithms were coded in C++ (using Borland’s TurboC++
compiler), The work was divided as follows :
Each member coded the kruskal’s algorithm implementation in C++
graphics. For the graphical side of the project, the team was split up in two -
one member coded the GUI (using TurboC++ Graphics Library) while the
other coded the main algorithm for the project.
System requirement
Hardware
Software
Introduction
Kruskal's algorithm is an algorithm in graph theory that finds a
minimum spanning tree for a connected weighted graph. This means it finds
a subset of the edges that forms a tree that includes every vertex, where the
total weight of all the edges in the tree is minimized. If the graph is not
connected, then it finds a minimum spanning forest (a minimum spanning
tree for each connected component). Kruskal's algorithm is an example of a
greedy algorithm.
It works as follows:
At the termination of the algorithm, the forest has only one component and
forms a minimum spanning tree of the graph.
Functional description
Performance
Where E is the number of edges in the graph and V is the number of
vertices, Kruskal's algorithm can be shown to run in O(E log E) time, or
equivalently, O(E log V) time, all with simple data structures. These running
times are equivalent because:
We can achieve this bound as follows: first sort the edges by weight
using a comparison sort in O(E log E) time; this allows the step "remove an
edge with minimum weight from S" to operate in constant time. Next, we
use a disjoint-set data structure to keep track of which vertices are in which
components. We need to perform O(E) operations, two 'find' operations and
possibly one union for each edge. Even a simple disjoint-set data structure
such as disjoint-set forests with union by rank can perform O(E) operations
in O(E log V) time. Thus the total time is O(E log E) = O(E log V).
Provided that the edges are either already sorted or can be sorted in linear
time (for example with counting sort or radix sort), the algorithm can use
more sophisticated disjoint-set data structures to run in O(E α(V)) time,
where α is the extremely slowly-growing inverse of the single-valued
Ackermann function.
Pseudocode/algorithm
1. function Kruskal(G)
2. Define an elementary cluster C(v) ← {v}.
3. Initialize a priority queue Q to contain all edges in G,
using the weights as keys.
4. Define a forest T ← Ø //T will ultimately contain
the edges of the MST
5. // n is total number of vertices
6. while T has fewer than n-1 edges do
7. // edge u,v is the minimum weighted route from/to v
8. (u,v) ← Q.removeMin()
9. // prevent cycles in T. add u,v only if T does not already
contain a path between u and v.
10. // the vertices has been added to the tree.
11. Let C(v) be the cluster containing v, and
let C(u) be the cluster containing u.
13. if C(v) ≠ C(u) then
14. Add edge (v,u) to T.
15. Merge C(v) and C(u) into one cluster, that is, union C(v) and C(u).
16. return tree T
Proof of correctness
The proof consists of two parts. First, it is proved that the algorithm
produces a spanning tree. Second, it is proved that the constructed spanning
tree is of minimal weight.
Spanning tree
Minimality
This is our original graph. The numbers near the arcs indicate their weight.
None of the arcs are highlighted.
fig. 1
AD and CE are the shortest arcs, with length 5, and AD has been arbitrarily
chosen, so it is highlighted.
fig. 2
CE is now the shortest arc that does not form a cycle, with length 5, so it is
highlighted as the second arc.
fig. 3
The next arc, DF with length 6, is highlighted using much the same method.
fig. 4
The next-shortest arcs are AB and BE, both with length 7. AB is chosen
arbitrarily, and is highlighted. The arc BD has been highlighted in red,
because there already exists a path (in green) between B and D, so it would
form a cycle (ABD) if it were chosen.
fig. 5
Finally, the process finishes with the arc EG of length 9, and the minimum
spanning tree is found.
fig. 7
Design details
Coding details
Testing plan
Limitation
# include "Mouse.h"
# include "Input.h"
# define MAX_VERTICES 10
# define MAX_EDGES 15
class Vertex
{
public:
int x;
int y;
int label;
private:
char Label[5];
public:
Vertex( ) { }
~Vertex( ) { }
Vertex V1;
Vertex V2;
private:
char Weight[5];
public:
Edge( ) { }
~Edge( ) { }
weight=_weight;
itoa(weight,Weight,10);
}
void Edge::ShowEdge( )
{
HideMouseCursor( );
setlinestyle(0,0,3);
setcolor(1);
line(V1.x,V1.y,V2.x,V2.y);
setlinestyle(0,0,0);
V1.ShowVertex( );
V2.ShowVertex( );
int x=(((V1.x+V2.x)/2)-6);
int y=(((V1.y+V2.y)/2)-8);
setcolor(11);
settextstyle(2,0,7);
outtextxy(x,y,Weight);
outtextxy((x+1),y,Weight);
outtextxy((x+1),(y+1),Weight);
ShowMouseCursor( );
}
void PrintText(const int x,const int y,const int number,const int
color=15)
{
char Number[10]={NULL};
itoa(number,Number,10);
moveto(x,y);
setcolor(color);
settextstyle(2,0,4);
outtext(Number);
}
int main( )
{
int driver=VGA;
int mode=VGAHI;
int error_code;
initgraph(&driver,&mode,"..\\Bgi");
error_code=graphresult( );
if(error_code!=grOk)
{
restorecrtmode( );
textmode(BW80);
clrscr( );
getch( );
exit(1);
}
cleardevice( );
setcolor(15);
rectangle(5,5,635,32);
rectangle(5,35,635,455);
rectangle(5,458,635,476);
setfillstyle(1,7);
bar(6,6,634,31);
setfillstyle(1,8);
bar(6,459,634,475);
bar(23,80,180,83);
settextstyle(2,0,7);
setcolor( 9);
outtextxy(119,6,"***** Kruskal's Algorithm *****");
outtextxy(120,6,"***** Kruskal's Algorithm *****");
outtextxy(120,7,"***** Kruskal's Algorithm *****");
setcolor(11);
outtextxy(24,60,"Prerequisites:");
outtextxy(25,60,"Prerequisites:");
outtextxy(25,61,"Prerequisites:");
int vertices=0;
int edges=0;
setcolor(15);
settextstyle(2,0,4);
outtextxy(25,96,"Enter the Total Number of Vertices ( 1-10 ) = ");
vertices=atoi(GetInput(295,95,2,15,0));
vertices=((vertices<1)?1:vertices);
vertices=((vertices>10)?10:vertices);
setcolor(15);
settextstyle(2,0,4);
outtextxy(25,115,"Enter the Total Number of Edges ( 1-15 ) = ");
edges=atoi(GetInput(295,114,2,15,0));
edges=((edges<0)?0:edges);
edges=((edges>15)?15:edges);
setfillstyle(1,8);
bar(23,380,115,383);
setcolor(11);
settextstyle(2,0,7);
outtextxy(24,360,"Read Me:");
outtextxy(25,360,"Read Me:");
outtextxy(25,361,"Read Me:");
setcolor(15);
settextstyle(2,0,4);
outtextxy(25,390,"* Press LeftMouseKey where you want to place a
Vertex.");
outtextxy(25,405,"* To draw an Edge, Click on a Vertex and Drag
the Mouse Pointer to the other Vertex and Release the");
outtextxy(25,418," LeftMouseKey, then enter the Weight of the
Edge.");
setcolor(14);
settextstyle(2,0,4);
outtextxy(15,461,"Press any Key to Continue...");
getch( );
setfillstyle(0,1);
bar(6,36,634,454);
setfillstyle(1,8);
bar(6,459,634,475);
setcolor(14);
settextstyle(2,0,4);
outtextxy(15,461,"Mark the Vertices Positions...");
Vertex V[MAX_VERTICES];
Edge E[MAX_EDGES];
InitMouse( );
ShowMouseCursor( );
SetMousePosition(320,240);
SetMouseRange(20,50,620,440);
int x;
int y;
for(int count=0;count<vertices;count++)
{
while(!LeftMouseKeyPressed( ));
GetMousePosition(&x,&y);
while(LeftMouseKeyPressed( ));
HideMouseCursor( );
V[count].SetVertex(x,y,count);
V[count].ShowVertex( );
ShowMouseCursor( );
}
HideMouseCursor( );
setfillstyle(1,8);
bar(6,459,634,475);
setcolor(14);
settextstyle(2,0,4);
outtextxy(15,461,"Draw the Edges and enter their weights.");
ShowMouseCursor( );
int i;
int j;
int flag=0;
int weight;
for(count=0;count<edges;)
{
flag=0;
do
{
while(!LeftMouseKeyPressed( ));
for(i=0;i<vertices;i++)
{
if(V[i].Hit( ) && LeftMouseKeyPressed( ))
{
GetMousePosition(&x,&y);
HideMouseCursor( );
setcolor(11);
circle(V[i].x,V[i].y,10);
ShowMouseCursor( );
flag=1;
break;
}
}
if(flag)break;
}
while(1);
setwritemode(1);
setcolor(11);
int x_end=x;
int y_end=y;
int prev_x=x;
int prev_y=y;
while(LeftMouseKeyPressed( ))
{
GetMousePosition(&x_end,&y_end);
if(x_end!=prev_x || y_end!=prev_y)
{
HideMouseCursor( );
line(x,y,prev_x,prev_y);
line(x,y,x_end,y_end);
ShowMouseCursor( );
prev_x=x_end;
prev_y=y_end;
}
}
flag=0;
for(j=0;j<vertices;j++)
{
if(V[j].Hit( ) && j!=i)
{
HideMouseCursor( );
setcolor(11);
circle(V[j].x,V[j].y,10);
ShowMouseCursor( );
flag=1;
break;
}
}
if(flag)
{
for(int k=0;k<count;k++)
{
if((E[k].V1.label==i && E[k].V2.label==j) ||
(E[k].V2.label==i && E[k].V1.label==j))
{
flag=0;
break;
}
}
}
setwritemode(0);
HideMouseCursor( );
if(flag)
{
line(x,y,x_end,y_end);
setfillstyle(1,8);
bar(6,459,634,475);
setcolor(15);
settextstyle(2,0,4);
outtextxy(15,461,"Enter the Edge Weight = ");
weight=atoi(GetInput(145,460,3,15,8));
setfillstyle(1,8);
bar(6,459,634,475);
if(count<(edges-1))
{
setcolor(14);
settextstyle(2,0,4);
outtextxy(15,461,"Draw the Edges and enter their
weights.");
}
weight=((weight<=0)?0:weight);
E[count].SetEdge(V[i],V[j],weight);
count++;
}
setfillstyle(0,1);
bar(6,36,634,454);
ShowMouseCursor( );
for(i=0;i<vertices;i++)
V[i].ShowVertex( );
for(i=0;i<count;i++)
E[i].ShowEdge( );
}
HideMouseCursor( );
setfillstyle(1,8);
bar(6,459,634,475);
setcolor(14);
settextstyle(2,0,4);
outtextxy(15,461,"Press any Key to apply Kruskal's Algorithm...");
getch( );
setfillstyle(0,1);
bar(6,36,634,454);
setfillstyle(1,8);
bar(6,459,634,475);
setcolor(15);
settextstyle(2,0,4);
outtextxy(15,461,"Applying Kruskals's Algorithm...");
ShowMouseCursor( );
for(count=0;count<vertices;count++)
V[count].ShowVertex( );
for(i=0;i<edges;i++)
{
for(int j=0;j<(edges-1);j++)
{
if(E[j].weight>=E[(j+1)].weight)
{
Edge Temp;
Temp=E[j];
E[j]=E[(j+1)];
E[(j+1)]=Temp;
}
}
}
int e_count=0;
int cycle_flag=0;
Edge _E[MAX_EDGES];
int mst[MAX_VERTICES][MAX_VERTICES]={0};
for(i=0;i<=vertices;i++)
{
mst[i][0]=i;
for(int j=1;j<vertices;j++)
mst[i][j]=-1;
}
for(count=0;count<edges;count++)
{
cycle_flag=0;
for(i=1;i<vertices;i++)
{
if(mst[E[count].V1.label][i]==E[count].V2.label ||
mst[E[count].V2.label][i]==E[count].V1.label)
cycle_flag=1;
}
if(!cycle_flag)
{
_E[e_count]=E[count];
_E[e_count].ShowEdge( );
e_count++;
for(i=1;i<vertices;i++)
{
if(mst[E[count].V1.label][i]==E[count].V2.label)
break;
if(mst[E[count].V1.label][i]==-1)
{
mst[E[count].V1.label][i]=E[count].V2.label;
break;
}
}
for(i=1;i<vertices;i++)
{
if(mst[E[count].V2.label][i]==E[count].V1.label)
break;
if(mst[E[count].V2.label][i]==-1)
{
mst[E[count].V2.label][i]=E[count].V1.label;
break;
}
}
for(i=0;i<vertices;i++)
{
for(int j=0;j<vertices;j++)
{
for(int k=1;k<vertices;k++)
{
if(mst[j][k]!=-1)
{
for(int l=1;l<vertices;l++)
{
if(mst[mst[j][k]][l]!=-1)
{
for(int m=0;m<vertices;m++)
{
if(mst[mst[j][k]][l]==mst[j][m])
break;
if(mst[j][m]==-1)
{
mst[j][m]=mst[mst[j][k]][l];
break;
}
}
}
}
}
}
}
}
HideMouseCursor( );
settextstyle(2,0,4);
do
{
setcolor(14);
outtextxy(530,461,"Press any Key...");
delay(250);
setcolor(8);
outtextxy(530,461,"Press any Key...");
delay(250);
}
while(!kbhit( ));
getch( );
setfillstyle(1,8);
bar(500,459,634,475);
ShowMouseCursor( );
}
}
HideMouseCursor( );
setfillstyle(0,1);
bar(6,36,634,454);
setfillstyle(1,8);
bar(6,459,634,475);
bar(23,80,90,83);
bar(23,230,122,233);
setcolor(11);
settextstyle(2,0,7);
outtextxy(24,60,"Given:");
outtextxy(25,60,"Given:");
outtextxy(25,61,"Given:");
outtextxy(24,210,"Solution:");
outtextxy(25,210,"Solution:");
outtextxy(25,211,"Solution:");
setcolor(15);
settextstyle(2,0,4);
moveto(50,98);
outtext("V = {");
for(count=0;count<vertices;count++)
{
PrintText((getx( )+3),gety( ),(count+1));
if(count<(vertices-1))
{
moveto((getx( )+3),gety( ));
outtext(",");
}
}
moveto(50,117);
outtext("E = {");
for(count=0;count<edges;count++)
{
if(count==7 || count==14)
moveto(83,(gety( )+15));
else
moveto((getx( )+3),gety( ));
outtext("(");
PrintText((getx( )+2),gety( ),(E[count].V1.label+1));
setcolor(15);
if(count<(edges-1))
{
moveto((getx( )+3),gety( ));
outtext(",");
}
}
moveto(50,248);
outtext("E = {");
for(count=0;count<e_count;count++)
{
if(e_count==7 || e_count==14)
moveto(83,(gety( )+15));
else
moveto((getx( )+3),gety( ));
outtext("(");
setcolor(15);
moveto(50,267);
outtext("Cost = ");
int cost=0;
for(count=0;count<e_count;count++)
{
cost+=_E[count].weight;
if(count<(e_count-1))
{
moveto((getx( )+3),gety( ));
outtext("+");
}
}
setcolor(14);
settextstyle(2,0,4);
outtextxy(15,461,"Press any Key to Exit.");
getch( );
closegraph( );
return 0;
}
char Input[10]={NULL};
int x_1=x;
int x_2=(x+(8*max_size)+15);
int y_1=y;
int y_2=(y+14);
setfillstyle(1,text_bgcolor);
bar(x_1,y_1,x_2,y_2);
int count=0;
int key_code=0;
char Key=NULL;
do
{
if(kbhit( ))
{
Key=NULL;
key_code=0;
Key=getch( );
key_code=int(Key);
count--;
Input[count]=NULL;
}
}
settextstyle(2,0,4);
setcolor(text_color);
moveto((x+5),(y+1));
outtext(Input);
int xx=getx( );
int yy=(gety( )+3);
while(!kbhit( ))
{
setcolor(text_color);
moveto(xx,yy);
outtext("-");
delay(250);
setcolor(text_bgcolor);
moveto(xx,yy);
outtext("-");
delay(200);
}
}
while(1);
return Input;
}
Source code: mouse.h
# include <graphics.h>
# include <fstream.h>
# include <dos.h>
void ShowMouseCursor( );
void HideMouseCursor( );
void SetMouseSpeed(int=0);
InReg.x.ax=0x0000;
int86(0x33,&InReg,&OutReg);
mouse_exists=1;
mouse_buttons=OutReg.x.bx;
return 1;
}
void ShowMouseCursor( )
{
if(cursor_visible || !mouse_exists)
return;
REGS InReg;
REGS OutReg;
InReg.x.ax=0x0001;
int86(0x33,&InReg,&OutReg);
cursor_visible=1;
}
void HideMouseCursor( )
{
if(!cursor_visible || !mouse_exists)
return;
REGS InReg;
REGS OutReg;
InReg.x.ax=0x0002;
int86(0x33,&InReg,&OutReg);
cursor_visible=0;
}
REGS InReg;
REGS OutReg;
InReg.x.ax=0x0004;
InReg.x.cx=x;
InReg.x.dx=y;
int86(0x33,&InReg,&OutReg);
}
if(!mouse_exists || !cursor_visible)
return;
REGS InReg;
REGS OutReg;
InReg.x.ax=0x0003;
int86(0x33,&InReg,&OutReg);
*x=OutReg.x.cx;
*y=OutReg.x.dx;
}
int x;
int y;
GetMousePosition(&x,&y);
return 0;
}
REGS InReg;
REGS OutReg;
InReg.x.ax=0x000B;
int86(0x33,&InReg,&OutReg);
if(OutReg.x.cx!=0x0000 || OutReg.x.dx!=0x0000)
return 1;
return 0;
}
REGS InReg;
REGS OutReg;
InReg.x.ax=0x0007;
InReg.x.cx=x_min;
InReg.x.dx=x_max;
int86(0x33,&InReg,&OutReg);
}
REGS InReg;
REGS OutReg;
InReg.x.ax=0x0008;
InReg.x.cx=y_min;
InReg.x.dx=y_max;
int86(0x33,&InReg,&OutReg);
}
SetMouseVerticalRange(y_min,y_max);
SetMouseHorizontalRange(x_min,x_max);
}
REGS InReg;
REGS OutReg;
InReg.x.ax=0x0003;
int86(0x33,&InReg,&OutReg);
if(OutReg.x.bx==0x0001 || OutReg.x.bx==0x0002 ||
(OutReg.x.bx==0x0004 && mouse_buttons==3))
return 1;
return 0;
}
REGS InReg;
REGS OutReg;
InReg.x.ax=0x0003;
int86(0x33,&InReg,&OutReg);
return ((OutReg.x.bx==0x0001)?1:0);
}
REGS InReg;
REGS OutReg;
InReg.x.ax=0x0003;
int86(0x33,&InReg,&OutReg);
return ((OutReg.x.bx==0x0002)?1:0);
}
REGS InReg;
REGS OutReg;
InReg.x.ax=0x0003;
int86(0x33,&InReg,&OutReg);
return ((OutReg.x.bx==0x0004)?1:0);
}
hotspot_x=((hotspot_x<0 || hotspot_x>15)?0:hotspot_x);
hotspot_y=((hotspot_y<0 || hotspot_y>15)?0:hotspot_y);
HideMouseCursor( );
REGS InReg;
REGS OutReg;
SREGS SegReg;
InReg.x.ax=0x0009;
InReg.x.bx=hotspot_x;
InReg.x.cx=hotspot_y;
InReg.x.dx=(unsigned)cursor;
segread(&SegReg);
SegReg.es=SegReg.ds;
int86x(0x33,&InReg,&OutReg,&SegReg);
ShowMouseCursor( );
}
void SetDefaultMouseCursor( )
{
if(!mouse_exists || !cursor_visible)
return;
0x3FFF, /* 0011111111111111 */
0x1FFF, /* 0001111111111111 */
0x0FFF, /* 0000111111111111 */
0x07FF, /* 0000011111111111 */
0x03FF, /* 0000001111111111 */
0x01FF, /* 0000000111111111 */
0x00FF, /* 0000000011111111 */
0x007F, /* 0000000001111111 */
0x003F, /* 0000000000111111 */
0x001F, /* 0000000000011111 */
0x001F, /* 0000000000011111 */
0x11FF, /* 0001000111111111 */
0x30FF, /* 0011000011111111 */
0xF8FF, /* 1111100011111111 */
0xF87F, /* 1111100001111111 */
0xFCFF, /* 1111110011111111 */
0x0000, /* 0000000000000000 */
0x4000, /* 0100000000000000 */
0x6000, /* 0110000000000000 */
0x7000, /* 0111000000000000 */
0x7800, /* 0111100000000000 */
0x7C00, /* 0111110000000000 */
0x7E00, /* 0111111000000000 */
0x7F00, /* 0111111100000000 */
0x7F80, /* 0111111110000000 */
0x7FC0, /* 0111111111000000 */
0x6C00, /* 0110110000000000 */
0x4400, /* 0100010000000000 */
0x0600, /* 0000011000000000 */
0x0200, /* 0000001000000000 */
0x0300, /* 0000001100000000 */
0x0000 /* 0000000000000000 */
};
SetMouseCursor(cursor,0,0);
}
int hotspot_x=0;
int hotspot_y=0;
char Signature[3]={NULL};
fstream File(CursorFile,ios::in|ios::nocreate);
if(!File)
return 2;
for(int count=0;count<32;count++)
File.read((char*)&cursor[count],sizeof(cursor[count]));
File.read((char*)&hotspot_x,sizeof(hotspot_x));
File.read((char*)&hotspot_y,sizeof(hotspot_y));
File.read((char*)&Signature,sizeof(Signature));
File.close( );
SetMouseCursor(cursor,hotspot_x,hotspot_y);
return 0;
}
REGS InReg;
REGS OutReg;
InReg.x.ax=0x001F;
int86(0x33,&InReg,&OutReg);
if(OutReg.x.ax==0x001F)
{
mouse_enable=0;
return 1;
}
return 0;
}
REGS InReg;
REGS OutReg;
InReg.x.ax=0x0020;
int86(0x33,&InReg,&OutReg);
if(OutReg.x.ax==0x0020)
{
mouse_enable=1;
return 1;
}
return 0;
}
speed=((speed==0)?64:128);
REGS InReg;
REGS OutReg;
InReg.x.ax=0x0013;
InReg.x.dx=speed;
int86(0x33,&InReg,&OutReg);
}
References