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