Skip to content

Commit c061a91

Browse files
committed
update prim alg
1 parent 3d14fb6 commit c061a91

File tree

6 files changed

+63
-150
lines changed

6 files changed

+63
-150
lines changed

include/heap.h

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,15 @@ namespace alg {
4949
int32_t m_max; // max heap size.
5050
KV * m_kvs; // key value pairs.
5151

52-
HashTable<int32_t, int32_t> * m_idx; // key -> idx
52+
HashTable<T, int32_t> * m_idx; // key -> idx
5353

5454
public:
5555
Heap(int max) {
5656
m_size = 0;
5757
m_max = max+1;
5858
m_kvs = new KV[m_max];
5959
m_kvs[0].key = INT_MIN;
60-
m_idx = new HashTable<int32_t, int32_t>(m_max);
60+
m_idx = new HashTable<T, int32_t>(m_max);
6161
};
6262

6363
~Heap() {
@@ -88,19 +88,19 @@ namespace alg {
8888
m_size++;
8989
m_kvs[m_size].key = key;
9090
m_kvs[m_size].value = value;
91-
(*m_idx)[key] = m_size;
91+
(*m_idx)[value] = m_size;
9292

9393
// Adjust its position
9494
int now = m_size;
9595
while(m_kvs[now/2].key > key) {
9696
m_kvs[now] = m_kvs[now/2];
97-
(*m_idx)[m_kvs[now/2].key] = now;
97+
(*m_idx)[m_kvs[now/2].value] = now;
9898
now /= 2;
9999
}
100100

101101
m_kvs[now].key = key;
102102
m_kvs[now].value = value;
103-
(*m_idx)[key] = now;
103+
(*m_idx)[value] = now;
104104
}
105105

106106
/**
@@ -159,7 +159,7 @@ namespace alg {
159159
// if the last key is less than the minimum key among both the children
160160
if(lastKey > m_kvs[child].key) {
161161
m_kvs[now] = m_kvs[child];
162-
(*m_idx)[m_kvs[now].key] = now; // record index
162+
(*m_idx)[m_kvs[now].value] = now; // record index
163163
}
164164
else { // It fits there
165165
break;
@@ -168,24 +168,24 @@ namespace alg {
168168

169169
m_kvs[now].key = lastKey;
170170
m_kvs[now].value= lastValue;
171-
(*m_idx)[lastKey] = now; // record index
171+
(*m_idx)[lastValue] = now; // record index
172172
}
173173

174174
/**
175175
* so called DECREASE KEY operation.
176176
* step 1. find the value
177177
* step 2. decrease the key to the newkey
178178
*/
179-
void decrease_key(int32_t oldkey, int32_t newkey) {
180-
int32_t index = (*m_idx)[oldkey];
179+
void decrease_key(T value, int32_t newkey) {
180+
int32_t index = (*m_idx)[value];
181181
if (index > m_size || index == 0) return; // value not found
182182
if (newkey >= m_kvs[index].key) return; // violate DECREASE meanning.
183183
T oldvalue = m_kvs[index].value;
184184

185185
int now = index;
186186
while(m_kvs[now/2].key > newkey) {
187187
m_kvs[now] = m_kvs[now/2];
188-
(*m_idx)[m_kvs[now].key] = now; // record index
188+
(*m_idx)[m_kvs[now].value] = now; // record index
189189
now /= 2;
190190
}
191191

include/prim_mst.h

Lines changed: 39 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -33,75 +33,6 @@
3333

3434
namespace alg {
3535
class Prim {
36-
private:
37-
/**
38-
* Prim's Adjacent Lists, for Prim's Algorithm caculation
39-
*/
40-
struct PrimAdjacent {
41-
Heap<Graph::Vertex*> heap; // binary heap representation of weight->node
42-
// the top of the heap is always the minimal element
43-
const Graph::Vertex & v;
44-
45-
PrimAdjacent(const Graph::Vertex & vertex, uint32_t num_neigh):heap(num_neigh),v(vertex) { }
46-
47-
struct list_head pa_node;
48-
};
49-
50-
/**
51-
* Prim's Graph, simplified to list.
52-
*/
53-
typedef struct list_head PrimGraph;
54-
private:
55-
PrimGraph m_pg;
56-
public:
57-
/**
58-
* construct Prim's DataStrcuture by a given graph
59-
*/
60-
Prim(const Graph & g) {
61-
INIT_LIST_HEAD(&m_pg);
62-
63-
Graph::Adjacent * a;
64-
list_for_each_entry(a, &g.list(), a_node){
65-
add_adjacent(*a);
66-
}
67-
}
68-
69-
~Prim() {
70-
PrimAdjacent * pa, *pan;
71-
list_for_each_entry_safe(pa, pan, &m_pg, pa_node){
72-
list_del(&pa->pa_node);
73-
delete pa;
74-
}
75-
}
76-
private:
77-
Prim(const Prim&);
78-
Prim& operator= (const Prim&);
79-
private:
80-
/**
81-
* add an adjacent list to prim's graph
82-
*/
83-
void add_adjacent(const Graph::Adjacent & a) {
84-
PrimAdjacent * pa = new PrimAdjacent(a.vertex(), a.num_neigh);
85-
list_add_tail(&pa->pa_node, &m_pg);
86-
87-
Graph::Vertex * v;
88-
list_for_each_entry(v, &a.v_head, v_node){
89-
pa->heap.insert(v->weight, v); // weight->vertex
90-
}
91-
}
92-
93-
/**
94-
* lookup up a given id
95-
* the related adjacent list is returned.
96-
*/
97-
PrimAdjacent * lookup(uint32_t id) const {
98-
PrimAdjacent * pa;
99-
list_for_each_entry(pa, &m_pg, pa_node){
100-
if (pa->v.id == id) { return pa;}
101-
}
102-
103-
return NULL;
104-
}
10536
public:
10637
/**
10738
* Prim's Algorithm.
@@ -118,66 +49,54 @@ namespace alg {
11849
*
11950
* Output: Vnew and Enew describe a minimal spanning tree
12051
*/
121-
Graph * run() {
52+
static Graph * run(const Graph & g, int32_t src_id) {
12253
UndirectedGraph * mst = new UndirectedGraph(); // empty set == Vnew
54+
// weight hash table
55+
HashTable<int32_t, int32_t> keys(g.vertex_count());
56+
// previous vertex hash table
57+
HashTable<int32_t, int32_t> pi(g.vertex_count());
12358

124-
// choose the first vertex as the starting point
125-
PrimAdjacent * pa;
126-
list_for_each_entry(pa, &m_pg, pa_node){ break; }
127-
const Graph::Vertex * v = &pa->v;
128-
mst->add_vertex(v->id);
129-
130-
// Prim's Algorithm
131-
while(true) {
132-
int weight = INT_MAX; // loop tmp variables
133-
uint32_t best_to;
134-
struct PrimAdjacent * best_from;
59+
// a binary heap
60+
Heap<uint32_t> Q(g.vertex_count());
13561

136-
// for each Vnew, find a new vertex in V that has minimal weight.
137-
Graph::Adjacent * a;
138-
list_for_each_entry(a, &mst->list(), a_node){
139-
pa = lookup(a->v.id);
140-
while (!pa->heap.is_empty()) { // find one neighbour
141-
v = pa->heap.min_value();
142-
if ((*mst)[v->id]==NULL) { // if new V appears
143-
if (pa->heap.min_key() < weight) {
144-
weight = pa->heap.min_key();
145-
best_to = v->id;
146-
best_from = pa;
147-
}
148-
break;
149-
} else {
150-
pa->heap.delete_min();
151-
}
152-
}
62+
// all vertices
63+
Graph::Adjacent * a;
64+
list_for_each_entry(a, &g.list(), a_node){
65+
if (a->v.id != src_id) {
66+
Q.insert(INT_MAX, a->v.id);
67+
keys[a->v.id] = INT_MAX;
15368
}
69+
}
15470

155-
if (weight != INT_MAX) {
156-
// congrats , new V & E
157-
mst->add_vertex(best_to);
158-
mst->add_edge(best_from->v.id, best_to, weight);
159-
best_from->heap.delete_min();
160-
} else break;
161-
};
71+
Q.insert(0, src_id);
72+
keys[src_id] = 0;
16273

163-
return mst;
164-
}
74+
while (!Q.is_empty()) {
75+
int32_t id = Q.min_value();
76+
Q.delete_min(); // remove u from Q
16577

166-
/**
167-
* print the PrimGraph
168-
*/
169-
void print() {
170-
struct PrimAdjacent * pa;
171-
printf("Prim Graph: \n");
172-
list_for_each_entry(pa, &m_pg, pa_node){
173-
printf("%d->{", pa->v.id);
174-
for(uint32_t i=0;i<pa->heap.count();i++) {
175-
Graph::Vertex * v = pa->heap[i];
176-
printf("id:%d->w:%d \t", v->id, v->weight);
78+
Graph::Adjacent * u = g[id]; // the vertex to process
79+
Graph::Vertex * v;
80+
list_for_each_entry(v, &u->v_head, v_node) {
81+
if (Q.contains(v->id) && v->weight < keys[v->id]) {
82+
pi[v->id] = id;
83+
Q.decrease_key(v->id, v->weight);
84+
keys[v->id] = v->weight;
85+
}
86+
}
87+
}
88+
89+
// create graph
90+
list_for_each_entry(a, &g.list(), a_node){
91+
mst->add_vertex(a->v.id);
92+
if (pi[a->v.id] != 0) {
93+
mst->add_vertex(pi[a->v.id]);
94+
mst->add_edge(pi[a->v.id], a->v.id, (*a)[pi[a->v.id]]->weight);
17795
}
178-
printf("}\n");
17996
}
180-
}
97+
98+
return mst;
99+
};
181100
};
182101
}
183102

include/undirected_graph.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,22 +128,23 @@ namespace alg {
128128
}
129129
/**
130130
* randomly generate a graph, for test purpose
131+
* start from 1
131132
*/
132133
static UndirectedGraph * randgraph(int nvertex) {
133134
UndirectedGraph * g = new UndirectedGraph;
134135
int i;
135136

136-
for(i=0;i<nvertex;i++) {
137+
for(i=1;i<=nvertex;i++) {
137138
g->add_vertex(i);
138139
}
139140

140141
// random connect
141-
for(i=0;i<nvertex;i++) {
142+
for(i=1;i<=nvertex;i++) {
142143
int j;
143144
for(j=i+1;j<nvertex;j++) {
144145
int dice = rand()%5;
145146
if (dice == 0) { // chance 20%
146-
int w = rand()%100;
147+
int w = rand()%100+1;
147148
g->add_edge(i, j, w);
148149
}
149150
}

src/dijkstra_demo.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ int main(void)
1818
g->printdot();
1919

2020
Graph::Adjacent * a;
21-
printf("finding Dijkstra shortest path starting from 0: \n");
22-
HashTable<int32_t,int32_t> * result = Dijkstra::run(*g, 0);
21+
printf("finding Dijkstra shortest path starting from 1: \n");
22+
HashTable<int32_t,int32_t> * result = Dijkstra::run(*g, 1);
2323

2424
list_for_each_entry(a, &g->list(), a_node){
2525
printf("previous of %u is ", a->v.id);
@@ -29,9 +29,9 @@ int main(void)
2929
}
3030
delete result;
3131

32-
printf("finding Dijkstra shortest path starting from 1: \n");
32+
printf("finding Dijkstra shortest path starting from 2: \n");
3333

34-
result = Dijkstra::run(*g, 1);
34+
result = Dijkstra::run(*g, 2);
3535
list_for_each_entry(a, &g->list(), a_node){
3636
printf("previous of %u is ", a->v.id);
3737
int32_t pre = (*result)[a->v.id];

src/heap_demo.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@ int main()
1717
printf("inserting: %d->%d\n", i, value);
1818
}
1919

20-
int index = 9;
21-
printf("decrease a key[%d] to %d\n", index, -1);
22-
heap.decrease_key(index, -1);
20+
printf("decrease a value[%d] to %d\n", 5, -1);
21+
heap.decrease_key(5, -1);
2322
while(!heap.is_empty()) {
2423
printf("deleting min: %d->%d\n", heap.min_key(), heap.min_value());
2524
heap.delete_min();

src/prim_mst_demo.cpp

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,18 @@
55

66
#include "undirected_graph.h"
77
#include "prim_mst.h"
8-
using namespace alg;
9-
108

119
int main(void)
1210
{
1311
using namespace alg;
1412
srand(time(NULL));
1513
int NVERTEX = 10;
16-
UndirectedGraph * g = UndirectedGraph::randgraph(NVERTEX);
14+
alg::UndirectedGraph * g = alg::UndirectedGraph::randgraph(NVERTEX);
1715
g->printdot();
1816
printf("Generating Prim's Graph: \n");
19-
Prim pg(*g);
20-
pg.print();
21-
22-
printf("Generating Minimal spanning tree: \n");
23-
Graph * mst = pg.run();
24-
mst->printdot();
25-
delete mst;
17+
Graph * prim = alg::Prim::run(*g, 1);
18+
prim->printdot();
19+
delete prim;
2620
delete g;
2721
return 0;
2822
}

0 commit comments

Comments
 (0)