-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtsort.c
111 lines (93 loc) · 2.18 KB
/
tsort.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
#include "tsort.h"
#include <stdio.h>
#include <stdio.h> /* for printf() */
#include <stdlib.h> /* for malloc(), free() */
struct tsort_t {
unsigned int length;
unsigned char *adjacent; /* adjacent[length][length] */
tsort_mark_t *visited; /* visited[length] */
tsort_callback_t callback; /* call on sorting */
};
static int visit(tsort_t *self, int to);
tsort_e tsort_init(tsort_t **self, unsigned int len, tsort_callback_t cb) {
tsort_t *tmp = NULL;
if (!self) {
return TSORT_EINVAL;
} else if (*self) {
return TSORT_EINVAL;
} else if (!len) {
return TSORT_EINVAL;
} else if (!cb) {
return TSORT_EINVAL;
} else if (!(tmp = malloc(sizeof(tsort_t)))) {
return TSORT_ENOMEM;
} else if (!(tmp->adjacent = malloc(len * len))) {
free(tmp);
return TSORT_ENOMEM;
} else if (!(tmp->visited = malloc(sizeof(tsort_mark_t) * len))) {
free(tmp->adjacent);
free(tmp);
return TSORT_ENOMEM;
} else {
tmp->length = len;
tmp->callback = cb;
*self = tmp;
return TSORT_EOK;
}
}
tsort_e tsort_free(tsort_t *self) {
if (!self) {
return TSORT_EINVAL;
} else {
free(self->visited);
free(self->adjacent);
free(self);
return TSORT_EOK;
}
}
tsort_e tsort_mark(tsort_t *self, unsigned int from, unsigned int to) {
if (!self) {
return TSORT_EINVAL;
} else if (self->length <= from) {
return TSORT_EINVAL;
} else if (self->length <= to) {
return TSORT_EINVAL;
} else {
/* accept from == to. */
self->adjacent[from * self->length + to] = 1;
return TSORT_EOK;
}
}
tsort_e tsort_sort(tsort_t *self) {
int from, to;
for (to = 0; to < self->length; to++) {
self->visited[to] = TSORT_MARK_NONE;
}
for (to = 0; to < self->length; to++) {
if (visit(self, to)) {
return TSORT_ECYCLIC;
}
}
return TSORT_EOK;
}
static int visit(tsort_t *self, int to) {
int j;
switch (self->visited[to]) {
case TSORT_MARK_VISITING:
return 1;
case TSORT_MARK_VISITED:
return 0;
default:
self->visited[to] = TSORT_MARK_VISITING;
for (j = 0; j < self->length; j++) {
if (!self->adjacent[to * self->length + j]) {
continue;
} else if (visit(self, j)) {
return 1;
}
}
self->visited[to] = TSORT_MARK_VISITED;
self->callback(to);
return 0;
}
}