|
|
1.1 root 1: /* topological sort
2: * input is sequence of pairs of items (blank-free strings)
3: * nonidentical pair is a directed edge in graph
4: * identical pair merely indicates presence of node
5: * output is ordered list of items consistent with
6: * the partial ordering specified by the graph
7: */
8: #include "stdio.h"
9:
10: /* the nodelist always has an empty element at the end to
11: * make it easy to grow in natural order
12: * states of the "live" field:*/
13: #define DEAD 0 /* already printed*/
14: #define LIVE 1 /* not yet printed*/
15: #define VISITED 2 /*used only in findloop()*/
16:
17: struct nodelist {
18: struct nodelist *nextnode;
19: struct predlist *inedges;
20: char *name;
21: int live;
22: } firstnode = {NULL, NULL, NULL, DEAD};
23:
24: /* a predecessor list tells all the immediate
25: * predecessors of a given node
26: */
27: struct predlist {
28: struct predlist *nextpred;
29: struct nodelist *pred;
30: };
31:
32: struct nodelist *index();
33: struct nodelist *findloop();
34: struct nodelist *mark();
35: char *malloc();
36: char *empty = "";
37:
38: /* the first for loop reads in the graph,
39: * the second prints out the ordering
40: */
41: main(argc,argv)
42: char **argv;
43: {
44: register struct predlist *t;
45: FILE *input = stdin;
46: register struct nodelist *i, *j;
47: int x;
48: char precedes[50], follows[50];
49: if(argc>1) {
50: input = fopen(argv[1],"r");
51: if(input==NULL)
52: error("cannot open ", argv[1]);
53: }
54: for(;;) {
55: x = fscanf(input,"%s%s",precedes, follows);
56: if(x==EOF)
57: break;
58: if(x!=2)
59: error("odd data",empty);
60: i = index(precedes);
61: j = index(follows);
62: if(i==j||present(i,j))
63: continue;
64: t = (struct predlist *)malloc(sizeof(struct predlist));
65: t->nextpred = j->inedges;
66: t->pred = i;
67: j->inedges = t;
68: }
69: for(;;) {
70: x = 0; /*anything LIVE on this sweep?*/
71: for(i= &firstnode; i->nextnode!=NULL; i=i->nextnode) {
72: if(i->live==LIVE) {
73: x = 1;
74: if(!anypred(i))
75: break;
76: }
77: }
78: if(x==0)
79: break;
80: if(i->nextnode==NULL)
81: i = findloop();
82: printf("%s\n",i->name);
83: i->live = DEAD;
84: }
85: }
86:
87: /* is i present on j's predecessor list?
88: */
89: present(i,j)
90: struct nodelist *i, *j;
91: {
92: register struct predlist *t;
93: for(t=j->inedges; t!=NULL; t=t->nextpred)
94: if(t->pred==i)
95: return(1);
96: return(0);
97: }
98:
99: /* is there any live predecessor for i?
100: */
101: anypred(i)
102: struct nodelist *i;
103: {
104: register struct predlist *t;
105: for(t=i->inedges; t!=NULL; t=t->nextpred)
106: if(t->pred->live==LIVE)
107: return(1);
108: return(0);
109: }
110:
111: /* turn a string into a node pointer
112: */
113: struct nodelist *
114: index(s)
115: register char *s;
116: {
117: register struct nodelist *i;
118: register char *t;
119: for(i= &firstnode; i->nextnode!=NULL; i=i->nextnode)
120: if(cmp(s,i->name))
121: return(i);
122: for(t=s; *t; t++) ;
123: t = malloc((unsigned)(t+1-s));
124: i->nextnode = (struct nodelist *)malloc(sizeof(struct nodelist));
125: if(i->nextnode==NULL||t==NULL)
126: error("too many items",empty);
127: i->name = t;
128: i->live = LIVE;
129: i->nextnode->nextnode = NULL;
130: i->nextnode->inedges = NULL;
131: i->nextnode->live = DEAD;
132: while(*t++ = *s++);
133: return(i);
134: }
135:
136: cmp(s,t)
137: register char *s, *t;
138: {
139: while(*s==*t) {
140: if(*s==0)
141: return(1);
142: s++;
143: t++;
144: }
145: return(0);
146: }
147:
148: error(s,t)
149: char *s, *t;
150: {
151: note(s,t);
152: exit(1);
153: }
154:
155: note(s,t)
156: char *s,*t;
157: {
158: fprintf(stderr,"tsort: %s%s\n",s,t);
159: }
160:
161: /* given that there is a cycle, find some
162: * node in it
163: */
164: struct nodelist *
165: findloop()
166: {
167: register struct nodelist *i, *j;
168: for(i= &firstnode; i->nextnode!=NULL; i=i->nextnode)
169: if(i->live==LIVE)
170: break;
171: note("cycle in data",empty);
172: i = mark(i);
173: if(i==NULL)
174: error("program error",empty);
175: for(j= &firstnode; j->nextnode!=NULL; j=j->nextnode)
176: if(j->live==VISITED)
177: j->live = LIVE;
178: return(i);
179: }
180:
181: /* depth-first search of LIVE predecessors
182: * to find some element of a cycle;
183: * VISITED is a temporary state recording the
184: * visits of the search
185: */
186: struct nodelist *
187: mark(i)
188: register struct nodelist *i;
189: {
190: register struct nodelist *j;
191: register struct predlist *t;
192: if(i->live==DEAD)
193: return(NULL);
194: if(i->live==VISITED)
195: return(i);
196: i->live = VISITED;
197: for(t=i->inedges; t!=NULL; t=t->nextpred) {
198: j = mark(t->pred);
199: if(j!=NULL) {
200: note(i->name,empty);
201: return(j);
202: }
203: }
204: return(NULL);
205: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.