1
//
implement of Binary heap
2 #include <stdio.h>
3 #include <malloc.h>
4
5
#define MAX_VERTEX_NUM 20
6
#define INFINITY 65535
7
8 typedef
int edgeType;
9
10 typedef
struct ArcNode
11 {
12
int adjIndex;
//
頂點下標
13 ArcNode *nextArc;
14 edgeType weight;
15 }ArcNode;
16
17 typedef
struct VNode
18 {
19 ArcNode* firstArc;
20 }VNode, AdjList[MAX_VERTEX_NUM];
21
22 typedef
struct
23 {
24 AdjList adjList;
25
int vexNum;
26
int edgeNum;
27 }ALGraph;
28
29
30
void initALGraph(ALGraph* Gp,
int cnt)
31 {
32 Gp->edgeNum =
0;
33 Gp->vexNum = cnt;
34
35
for (
int i =
0; i < cnt; i++)
36 {
37 Gp->adjList[i].firstArc = NULL;
38 }
39 }
40
41
void insertArc(ALGraph* Gp,
int head,
int tail,
int w)
42 {
43 ArcNode* arcNodePt = (ArcNode*)malloc(
sizeof(
struct ArcNode));
44
if (arcNodePt == NULL)
45 {
46
return;
47 }
48
49 arcNodePt->nextArc = NULL;
50 arcNodePt->adjIndex = tail;
51 arcNodePt->weight = w;
52
53 ArcNode* tailPt = Gp->adjList[head].firstArc;
54
if (tailPt == NULL)
55 {
56 Gp->adjList[head].firstArc = arcNodePt;
57 }
58
else
59 {
60
while (tailPt->nextArc != NULL)
61 {
62 tailPt = tailPt->nextArc;
63 }
64 tailPt->nextArc = arcNodePt;
65 }
66 Gp->edgeNum++;
67 }
68
69
70
void displayGraph(ALGraph G)
71 {
72 ArcNode* arcNodePt;
73
74
for (
int i =
0; i < G.vexNum; i++)
75 {
76 arcNodePt = G.adjList[i].firstArc;
77 printf(
"
vertex(%d):
", i);
78
79
while (arcNodePt != NULL)
80 {
81 printf(
"
->%d(weight: %d)
", arcNodePt->adjIndex, arcNodePt->weight);
82 arcNodePt = arcNodePt->nextArc;
83 }
84 printf(
"
\n
");
85 }
86 }
87
88
void printRoute(
int start,
int node,
int* pi)
89 {
90 printf(
"
%d
", node);
91
do
92 {
93 printf(
"
<-%d
", pi[node]);
94 node = pi[node];
95 }
while (node != start);
96
97 }
98
99
int getEdgeWeight(ALGraph G,
int head,
int tail)
100 {
101 ArcNode* arcNodePt = G.adjList[head].firstArc;
102
103
while (arcNodePt != NULL)
104 {
105
if (arcNodePt->adjIndex == tail)
106 {
107
return arcNodePt->weight;
108 }
109 arcNodePt = arcNodePt->nextArc;
110 }
111
112
return INFINITY;
113 }
114
115
116
void minHeapify(
int* Q,
int* d,
int i)
117 {
118
int l =
2 * i;
119
int r =
2 * i +
1;
120
int smallest = i;
121
122
if (l <= Q[
0] && d[Q[l]] < d[Q[i]])
123 {
124 smallest = l;
125 }
126
127
128
if (r <= Q[
0] && d[Q[r]] < d[Q[smallest]])
129 {
130 smallest = r;
131 }
132
133 printf(
"
smallest = %d\n
", smallest, i, l ,r);
134
135
if (smallest != i)
136 {
137
int temp = Q[i];
138 Q[i] = Q[smallest];
139 Q[smallest] = temp;
140
141 minHeapify(Q, d, smallest);
142 }
143 }
144
145
int extractMin(
int* Q,
int* d)
146 {
147
int min;
148 min = Q[
1];
149 Q[
1] = Q[Q[
0]];
150 Q[
0] = Q[
0] -
1;
151
152
return min;
153 }
154
155
void buildMinHeap(
int* Q,
int* d,
int start)
156 {
157
for (
int i = Q[
0]/
2; i >=
1; i--)
158 {
159 minHeapify(Q, d, i);
160 }
161 }
162
163
void initSingleSource(ALGraph G,
int start,
int* di,
int* pi)
164 {
165
for (
int i =
0; i < G.vexNum; i++)
166 {
167 di[i] = INFINITY;
168 pi[i] =
0;
169 }
170
171 ArcNode* arcNodePt = G.adjList[start].firstArc;
172
while (arcNodePt != NULL)
173 {
174 di[arcNodePt->adjIndex] = arcNodePt->weight;
175 arcNodePt = arcNodePt->nextArc;
176 }
177
178 di[start] =
0;
179 }
180
181
182
void dijkstra(ALGraph G,
int start,
int* d,
int* pi,
int* Q)
183 {
184
int u, v;
185
int visit[MAX_VERTEX_NUM] = {
0};
186
187 initSingleSource(G, start, d, pi);
188
189 visit[start] =
1;
190
191 Q[
0] = G.vexNum;
192
for (
int i =
1; i <= Q[
0]; i++)
193 {
194 Q[i] = i -
1;
195 }
196
197
198
while (Q[
0] !=
0)
199 {
200 buildMinHeap(Q, d, start);
201
202
//
在提取最小點後, 利用每次從新建堆來保持堆的性質。 正常作法是將最後一個結點放到空結點,作下潛操做,複雜度O(logN)。
203
//
建堆複雜度O(N), 效率稍低一點。
204 u = extractMin(Q, d);
205
206
if (u == start)
207 {
208
continue;
209 }
210
211 printf(
"
extract min node: %d\n
", u);
212
213 visit[u] =
1;
214 ArcNode* arcNodePt = G.adjList[u].firstArc;
215
while (arcNodePt != NULL)
216 {
217 v = arcNodePt->adjIndex;
218 printf(
"
adjacent to : %d, d[v]=%d, d[u]=%d, w(u,v)=%d\n
", v, d[v], d[u], getEdgeWeight(G, u, v));
219
220
//
鬆弛操做
221
if (!visit[v] && (d[v] > d[u] + getEdgeWeight(G, u, v)))
222 {
223 d[v] = d[u] + getEdgeWeight(G, u, v);
224 printf(
"
update d[%d]=%d\n
", v, d[v]);
225 pi[v] = u;
226 printf(
"
pi[%d]=%d\n\n
", v, pi[v]);
227 }
228 arcNodePt = arcNodePt->nextArc;
229 }
230
231 }
232
233
234
235
236
237 }
238
239
240
int main(
int argc,
char
const *argv[])
241 {
242
#define startpoint 0
243 ALGraph G;
244 ALGraph* Gp = &G;
245
246 initALGraph(Gp,
5);
247 insertArc(Gp,
0,
1,
10);
248 insertArc(Gp,
0,
3,
5);
249 insertArc(Gp,
1,
2,
1);
250 insertArc(Gp,
1,
3,
2);
251 insertArc(Gp,
2,
4,
4);
252 insertArc(Gp,
3,
1,
3);
253 insertArc(Gp,
3,
2,
9);
254 insertArc(Gp,
3,
4,
2);
255 insertArc(Gp,
4,
2,
6);
256 insertArc(Gp,
4,
0,
7);
257
258 printf(
"
print the graph: \n
");
259 displayGraph(G);
260
261
int d[MAX_VERTEX_NUM];
262
int pi[MAX_VERTEX_NUM];
263
int Q[MAX_VERTEX_NUM +
1];
//
Q[0]保存個數
264
265
266 dijkstra(G, startpoint, d, pi, Q);
267
268
for (
int i =
0; i < G.vexNum; i++)
269 {
270 printf(
"
From %d to %d length is %d. \n
", startpoint, i, d[i]);
271 printf(
"
Path :
");
272
273 printRoute(startpoint, i, pi);
274 printf(
"
\n
");
275 }
276
277
return
0;
278 }