-
Notifications
You must be signed in to change notification settings - Fork 0
/
algorithm.c
188 lines (154 loc) · 6.78 KB
/
algorithm.c
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
#include <stdio.h>
#include <stdlib.h>
#include "algorithm.h"
#include "store.h"
int bfs (graph_t g, int start_vertex) {
edge_t edge = g->edge;
int n = g->rows * g->columns;
int *visited = calloc (n, sizeof *(visited));
int *queue = calloc (n, sizeof *(queue));
int k = 0;
edge_t tmp;
visited[start_vertex] = 1; /* ustawiamy wierzchołek, od którego zaczynamy jako odwiedzony
* działanie kolejki:
* kolejka - tablica n elementowa, gdzie n to liczba wierzchołków w grafie
* k - liczba dodanych wierzchołków do kolejki
*
* do kolejki dodajemy wierzchołki, na które możemy przejść
* z badanego wierzchołka (jeżeli nie zostały już wcześniej odwiedzone)
*
* dodając wierzchołek do kolejki ustawiamy jego indeks na k-ty element kolejki
* oraz k+1 element kolejki ustawiamy jako -1 (jeżeli k+1 nie jest równe n-1)
* i zwiększamy k o jeden
*
* jeżeli aktualnie badany wierzchołek w kolejce (queue[i]) to -1 to znaczy, że
* graf jest niespójny, bo z poprzednio badanego wierzchołka z kolejki (queue[i-1])
* nie było już przejść na żaden jeszcze nieodwiedzony wierzchołek
*
* jeżeli indeksy wszystkich wierzchołków zostały dodane do kolejki
* czyli k = n, to graf spójny
*/
queue[k] = start_vertex;
if (k != n-1)
queue[k+1] = -1;
k++;
for (int i = 0; i < n; i++) {
if (queue[i] == -1) {
free (visited);
free (queue);
return 1;
}
if (k == n) {
free (visited);
free (queue);
return 0;
}
if (edge[queue[i]].weight == -1 && edge[queue[i]].vertex_index == -1) // waga -1 i wierzchołek na który przechodzimy z badanego -1 czyli nie ma krawędzi
continue;
int current = edge[queue[i]].vertex_index; // indeks wierzchołka, z którym aktualnie badany wierzchołek ma krawędź - jeżeli nie był odwiedzony to dodajemy do kolejki */
if (visited[current] != 1) {
queue[k] = current;
if (k != n-1)
queue[k+1] = -1;
k++;
visited[current] = 1;
}
tmp = edge[queue[i]].next;
while (tmp != NULL) {
if (visited[tmp->vertex_index] != 1) {
visited[tmp->vertex_index] = 1;
queue[k] = tmp->vertex_index;
if (k != n-1)
queue[k+1] = -1;
k++;
}
tmp = tmp->next;
}
}
free (visited);
free (queue);
return 0;
}
dijkstra_t dijkstra (graph_t g, int start_vertex) {
edge_t edge = g->edge;
int n = g->rows * g->columns;
int *visited = calloc (n, sizeof *(visited));
int *queue = calloc (n, sizeof *(queue));
int k = 0;
edge_t tmp;
dijkstra_t d = dijkstra_init (n);
if (d == NULL) {
free (visited);
free (queue);
lastError = MEMORY_ERR;
return NULL;
}
visited[start_vertex] = 1;
queue[k] = start_vertex;
if (k != n-1)
queue[k+1] = -1;
k++;
for (int i = 0; i < n; i++) {
if (queue[i] == -1) {
free (visited);
free (queue);
return d;
}
if (edge[queue[i]].weight == -1 && edge[queue[i]].vertex_index == -1)
continue;
int current = edge[queue[i]].vertex_index;
if (visited[current] != 1) {
queue[k] = current;
if (k != n-1)
queue[k+1] = -1;
k++;
visited[current] = 1;
}
double *edge_vertex_sp = &d[edge[queue[i]].vertex_index].shortest_path; // sp - shortest_path długość najkrótszej ścieżki od wierzchołka startowego do wierzchołka, z którym aktualnie
// badany wierzchołek ma krawędź
double *current_vertex_sp = &d[queue[i]].shortest_path; // dlugosc najkrotszej sciezki od wierzcholka startowego do aktualnie badanego wierzcholka
double *edge_weight = &edge[queue[i]].weight; // waga przejścia z aktualnie badanego wierzchołka na wierzchołek, z którym ma krawędź
int *edge_vertex_lvi = &d[edge[queue[i]].vertex_index].last_vertex_index; // lvi - last_vertex_index indeks poprzedniego wierzchołka, z którego wcześniej przeszliśmy na ten wierzchołek, z
// którym aktualnie badany wierzchołek ma krawędź
if ( (*edge_weight) <= 0) { // waga krawędzi powinna być większa od 0
lastError = FORMAT_ERR;
free (visited);
free (queue);
free (d);
return NULL;
}
if ( (*edge_vertex_sp) == 0 || (*edge_vertex_sp) > (*current_vertex_sp) + (*edge_weight) ) {
*edge_vertex_sp = (*current_vertex_sp) + (*edge_weight);
*edge_vertex_lvi = queue[i];
}
tmp = edge[queue[i]].next;
while (tmp != NULL) {
if (visited[tmp->vertex_index] != 1) {
visited[tmp->vertex_index] = 1;
queue[k] = tmp->vertex_index;
if (k != n-1)
queue[k+1] = -1;
k++;
}
edge_vertex_sp = &d[tmp->vertex_index].shortest_path;
current_vertex_sp = &d[queue[i]].shortest_path;
edge_weight = &tmp->weight;
edge_vertex_lvi = &d[tmp->vertex_index].last_vertex_index;
if ( (*edge_weight) <= 0) {
lastError = FORMAT_ERR;
free (visited);
free (queue);
free (d);
return NULL;
}
if ( (*edge_vertex_sp) == 0 || (*edge_vertex_sp) > (*current_vertex_sp) + (*edge_weight) ) {
*edge_vertex_sp = (*current_vertex_sp) + (*edge_weight);
*edge_vertex_lvi = queue[i];
}
tmp = tmp->next;
}
}
free (visited);
free (queue);
return d;
}