1 /* tsort.c -- topological sort for vlock, the VT locking program for linux
3 * This program is copyright (C) 2007 Frank Benkstein, and is free
4 * software which is freely distributable under the terms of the
5 * GNU General Public License version 2, included as the file COPYING in this
6 * distribution. It is NOT public domain software, and any
7 * redistribution not permitted by the GNU General Public License is
8 * expressly forbidden without prior written permission from
20 /* Get the zeros of the graph, i.e. nodes with no incoming edges. */
21 static GList
*get_zeros(GList
*nodes
, GList
*edges
)
23 GList
*zeros
= g_list_copy(nodes
);
25 for (GList
*edge_item
= edges
;
27 edge_item
= g_list_next(edge_item
)) {
28 struct edge
*e
= edge_item
->data
;
29 zeros
= g_list_remove(zeros
, e
->successor
);
35 /* Check if the given node is a zero. */
36 static bool is_zero(void *node
, GList
*edges
)
38 for (GList
*edge_item
= edges
;
40 edge_item
= g_list_next(edge_item
)) {
41 struct edge
*e
= edge_item
->data
;
43 if (e
->successor
== node
)
50 /* For the given directed graph, generate a topological sort of the nodes.
52 * Sorts the list and deletes all edges. If there are circles found in the
53 * graph or there are edges that have no corresponding nodes the erroneous
56 * The algorithm is taken from the Wikipedia:
58 * http://en.wikipedia.org/w/index.php?title=Topological_sorting&oldid=153157450#Algorithms
61 GList
*tsort(GList
*nodes
, GList
**edges
)
63 /* Retrieve all zeros. */
64 GList
*zeros
= get_zeros(nodes
, *edges
);
66 GList
*sorted_nodes
= NULL
;
68 /* While the list of zeros is not empty ... */
69 while (zeros
!= NULL
) {
70 /* ... take the first zero and remove it and ...*/
71 void *zero
= zeros
->data
;
72 zeros
= g_list_delete_link(zeros
, zeros
);
74 /* ... add it to the list of sorted nodes. */
75 sorted_nodes
= g_list_append(sorted_nodes
, zero
);
77 /* Then look at each edge ... */
78 for (GList
*edge_item
= *edges
;
80 struct edge
*e
= edge_item
->data
;
82 GList
*tmp
= g_list_next(edge_item
);
84 /* ... that has this zero as its predecessor ... */
85 if (e
->predecessor
== zero
) {
86 /* ... and remove it. */
87 *edges
= g_list_delete_link(*edges
, edge_item
);
89 /* If the successor has become a zero now ... */
90 if (is_zero(e
->successor
, *edges
))
91 /* ... add it to the list of zeros. */
92 zeros
= g_list_append(zeros
, e
->successor
);
101 /* If all edges were deleted the algorithm was successful. */
102 if (*edges
!= NULL
) {
103 g_list_free(sorted_nodes
);