Skip to content

Commit 2685718

Browse files
committed
Merge pull request xtaci#9 from xmuliang/master
add kruskal minimum spanning tree algorithm
2 parents 1306d62 + 6b23c98 commit 2685718

File tree

2 files changed

+275
-0
lines changed

2 files changed

+275
-0
lines changed

include/kruskal_mst.h

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
/*******************************************************************************
2+
* DANIEL'S ALGORITHM IMPLEMENTAIONS
3+
*
4+
* /\ | _ _ ._ o _|_ |_ ._ _ _
5+
* /--\ | (_| (_) | | |_ | | | | | _>
6+
* _|
7+
*
8+
* Kruskal'S ALGORITHM -- MINIMUM SPANNING TREE
9+
*
10+
* Features:
11+
*
12+
* Kruskal's algorithm is a greedy algorithm in graph theory that finds a minimum spanning tree for a connected weighted graph.
13+
* This means it finds a subset of the edges that forms a tree that includes every vertex,
14+
* where the total weight of all the edges in the tree is minimized. If the graph is not connected,
15+
* then it finds a minimum spanning forest (a minimum spanning tree for each connected component).
16+
* This algorithm first appeared in Proceedings of the American Mathematical Society, pp. 48–50 in 1956,
17+
* and was written by Joseph Kruskal.
18+
*
19+
* http://en.wikipedia.org/wiki/Kruskal's_algorithm
20+
*
21+
*By Contibutor:xmuliang
22+
******************************************************************************/
23+
24+
#ifndef __KRUSKAL_MST_H__
25+
#define __KRUSKAL_MST_H__
26+
27+
#include <stdio.h>
28+
#include <stdlib.h>
29+
#include "undirected_graph.h"
30+
#include "double_linked_list.h"
31+
#include "heap.h"
32+
33+
namespace alg
34+
{
35+
class Kruskal
36+
{
37+
private:
38+
/**
39+
* Kruskal's Adjacent Lists, for Kruskal's Algorithm caculation
40+
*/
41+
struct KruskalAdjacent {
42+
Heap<Graph::Vertex*> heap; // binary heap representation of weight->node
43+
// the top of the heap is always the minimal element
44+
const Graph::Vertex & v;
45+
46+
KruskalAdjacent(const Graph::Vertex & vertex, uint32_t num_neigh):heap(num_neigh),v(vertex) { }
47+
48+
struct list_head pa_node;
49+
};
50+
51+
/**
52+
* Kruskal's Graph, simplified to list.
53+
*/
54+
typedef struct list_head KruskalGraph;
55+
private:
56+
KruskalGraph m_pg;
57+
uint32_t num_vertex;
58+
public:
59+
/**
60+
* construct Kruskal's DataStrcuture by a given graph
61+
*/
62+
Kruskal(const Graph & g)
63+
{
64+
INIT_LIST_HEAD(&m_pg);
65+
66+
Graph::Adjacent * a;
67+
list_for_each_entry(a, &g.list(), a_node){
68+
add_adjacent(*a);
69+
}
70+
this->num_vertex=g.vertex_count();
71+
}
72+
73+
~Kruskal()
74+
{
75+
KruskalAdjacent * pa, *pan;
76+
list_for_each_entry_safe(pa, pan, &m_pg, pa_node){
77+
list_del(&pa->pa_node);
78+
delete pa;
79+
}
80+
}
81+
private:
82+
Kruskal(const Kruskal&);
83+
Kruskal& operator= (const Kruskal&);
84+
private:
85+
/**
86+
* add an adjacent list to Kruskal's graph
87+
*/
88+
void add_adjacent(const Graph::Adjacent & a)
89+
{
90+
KruskalAdjacent * pa = new KruskalAdjacent(a.vertex(), a.num_neigh);
91+
list_add_tail(&pa->pa_node, &m_pg);
92+
93+
Graph::Vertex * v;
94+
list_for_each_entry(v, &a.v_head, v_node){
95+
pa->heap.insert(v->weight, v); // weight->vertex
96+
}
97+
}
98+
99+
/**
100+
* lookup up a given id
101+
* the related adjacent list is returned.
102+
*/
103+
KruskalAdjacent * lookup(uint32_t id) const
104+
{
105+
KruskalAdjacent * pa;
106+
list_for_each_entry(pa, &m_pg, pa_node){
107+
if (pa->v.id == id) { return pa;}
108+
}
109+
110+
return NULL;
111+
}
112+
public:
113+
/**
114+
* Kruskal's Algorithm.
115+
*
116+
* Input: A non-empty connected weighted graph with vertices V and edges E
117+
* (the weights can be negative).
118+
*
119+
* Initialize: Enew = {}
120+
*
121+
* Repeat until edges = V-1:
122+
* Choose an edge {u, v} with minimal weight and promise that two nodes come from different set
123+
*
124+
* Output: Vnew and Enew describe a minimal spanning tree
125+
*/
126+
Graph * run()
127+
{
128+
UndirectedGraph * mst = new UndirectedGraph(); // empty Grapph
129+
130+
uint32_t mark[num_vertex];// mark the different set
131+
for(uint32_t i=0;i<num_vertex;i++)
132+
mark[i]=i; // initialize the mark array with the unique value
133+
134+
const Graph::Vertex * v;
135+
KruskalAdjacent * pa;
136+
uint32_t flag=0; //record the edge to be added into the mst
137+
uint32_t total_nodes=num_vertex; //nodes of the Kruskal
138+
139+
140+
while(true)
141+
{
142+
int weight = INT_MAX;
143+
uint32_t best_to;
144+
struct KruskalAdjacent * best_from;
145+
146+
//choose the smallest edge from the original graph
147+
list_for_each_entry(pa, &m_pg, pa_node){
148+
if(!pa->heap.is_empty()&&pa->heap.min_key()<weight)
149+
{
150+
weight = pa->heap.min_key();
151+
v = pa->heap.min_value();
152+
best_to = v->id;
153+
best_from = pa;
154+
}
155+
}
156+
157+
//loop until the chosen edges to total_nodes-1
158+
if (flag<(total_nodes-1)&&(weight != INT_MAX)) {
159+
160+
//if the node not been added,construct it
161+
if((*mst)[best_from->v.id]==NULL)
162+
{
163+
mst->add_vertex(best_from->v.id);
164+
}
165+
166+
if((*mst)[best_to]==NULL)
167+
{
168+
mst->add_vertex(best_to);
169+
}
170+
171+
//two nodes must belongs to set,to keep uncircle
172+
if(mark[best_from->v.id]!=mark[best_to])
173+
{
174+
175+
mst->add_edge(best_from->v.id, best_to, weight);
176+
177+
uint32_t tmp=mark[best_to];
178+
for(uint32_t i=0;i<num_vertex;i++)
179+
{
180+
if(mark[i]==tmp)
181+
mark[i]=mark[best_from->v.id];
182+
}
183+
flag++;
184+
}
185+
186+
best_from->heap.delete_min();
187+
lookup(best_to)->heap.delete_min();
188+
} else break;
189+
190+
191+
}
192+
193+
return mst;
194+
}
195+
196+
/**
197+
* print the KruskalGraph
198+
*/
199+
void print()
200+
{
201+
struct KruskalAdjacent * pa;
202+
printf("Kruskal Graph: \n");
203+
list_for_each_entry(pa, &m_pg, pa_node){
204+
printf("%d->{", pa->v.id);
205+
for(uint32_t i=0;i<pa->heap.count();i++) {
206+
Graph::Vertex * v = pa->heap[i];
207+
printf("id:%d->w:%d \t", v->id, v->weight);
208+
}
209+
printf("}\n");
210+
}
211+
}
212+
};
213+
}
214+
215+
#endif //
216+

src/kruskal_mst_demo.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#include <stdio.h>
2+
#include <stdio.h>
3+
#include <stdlib.h>
4+
#include <time.h>
5+
6+
#include "undirected_graph.h"
7+
#include "kruskal_mst.h"
8+
9+
using namespace alg;
10+
/**
11+
* randomly generate a graph, for test purpose
12+
*/
13+
UndirectedGraph * randgraph(int nvertex)
14+
{
15+
UndirectedGraph * g = new UndirectedGraph;
16+
int i;
17+
18+
for(i=0;i<nvertex;i++) {
19+
g->add_vertex(i);
20+
}
21+
22+
// random connect
23+
for(i=0;i<nvertex;i++) {
24+
int j;
25+
for(j=i+1;j<nvertex;j++) {
26+
int dice = rand()%2;
27+
if (dice == 0) { // chance 50%,rise the possibility to produce a connected graph
28+
int w = rand()%100;
29+
g->add_edge(i, j, w);
30+
}
31+
}
32+
}
33+
34+
35+
36+
37+
return g;
38+
}
39+
40+
int main(void)
41+
{
42+
using namespace alg;
43+
srand(time(NULL));
44+
int NVERTEX = 10;
45+
UndirectedGraph * g = randgraph(NVERTEX);
46+
g->print();
47+
printf("Generating Kruskal's Graph: \n");
48+
Kruskal pg(*g);
49+
pg.print();
50+
51+
52+
printf("Generating Minimal spanning tree: \n");
53+
Graph * mst = pg.run();
54+
mst->print();
55+
delete mst;
56+
delete g;
57+
return 0;
58+
}
59+

0 commit comments

Comments
 (0)