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