#include <stdio.h>
/**************** Some Constants *****************/
#define Menu1 "/r/t/t/tTopological Sort Demo"
#define Menu2 "/t/t/tAuthor: Huping"
#define Menu3 "/t/t/tUpdate: Dec-01-2008"
#define Menu4 "--------------------------------------------------------------------------------"
#define MAX_VEX_NUM 30
#define VEX_NUM 11
#define STACK_INIT_SIZE VEX_NUM
#define STACK_INCREMENT 10
#define EDGE_FILE "edges.txt"
#define BUFFER_LENGTH 100
/**************** Satck Type *****************/
typedef struct{
int *base;
int *top;
int stackSize;
}Stack;
/**************** Graph Type *****************/
typedef enum { DG, UDG, DN, UDN } GraphKind;
typedef struct {
int adj;
}AdjMatrix[MAX_VEX_NUM+1][MAX_VEX_NUM+1];
typedef struct {
char *vexs[MAX_VEX_NUM+1];
AdjMatrix edges;
int vexNum, edgeNum;
GraphKind kind;
}MGraph;
/**************** Global Variable *****************/
int Indegree[VEX_NUM+1];
int TopOrdering[VEX_NUM+1];
Stack s;
/************* Initial the Stack **************/
void InitStack(){
s.base=s.top=(int *)malloc(STACK_INIT_SIZE*sizeof(int));
if(s.base==NULL)
exit(-1);
s.stackSize=STACK_INIT_SIZE;
}
/************* Pop the Top Element of Stack **************/
int Pop(){
if(StackEmpty())
return -1;
else{
s.top=s.top-1;
return *(s.top);
}
}
/************* Push an Element into the top of Stack **************/
void Push(int e){
if(s.top-s.base>=s.stackSize){
s.base=(int *)realloc(s.base, (s.stackSize+STACK_INCREMENT)*sizeof(int));
if(s.base==NULL)
exit(-1);
s.top=s.base+s.stackSize;
s.stackSize=s.stackSize+STACK_INCREMENT;
}
*(s.top)=e;
s.top=s.top+1;
}
/************* Is the Stack Empty? **************/
int StackEmpty(){
if(s.base==s.top)
return 1;
else
return 0;
}
/**************** Create Graph using egdes from file *****************/
MGraph CreateDG() {
int i, j, n=0, v1, v2;
FILE *fp;
char line[BUFFER_LENGTH];
MGraph G;
G.vexNum=VEX_NUM;
/* open a text file with read only */
if((fp=fopen(EDGE_FILE, "rt"))==NULL) {
printf("[ERROR]: Can not open data file: %s!/n", EDGE_FILE);
exit(-1);
}
printf("[INFO]: Loading edges data from %s.../n", EDGE_FILE);
for(i=1; i<=G.vexNum; i++)
for(j=1; j<=G.vexNum; j++)
G.edges[i][j].adj=0;
while(!feof(fp)) {
/* read one line at a time */
fgets(line, BUFFER_LENGTH, fp);
/* match the format of edge: <v1,v2> */
sscanf(line, "<%d,%d>", &v1, &v2);
G.edges[v1][v2].adj=1;
n++;
}
fclose(fp);
printf("[INFO]: %d edges have been loaded from %s successfully!/n", n, EDGE_FILE);
printf("[INFO]: A directed graph have been created successfully!/n");
G.edgeNum=n;
G.kind=DG;
return G;
}
/************* Print the Matrix of Graph **************/
void PrintAdjMatrix(MGraph G) {
int i,j;
printf("/n/t/t--------- Adjacent Matrix (/'-/' means 0)--------");
for(i=1; i<=G.vexNum; i++) {
printf("/n/t/t");
for(j=1;j<=G.vexNum; j++) {
if(G.edges[i][j].adj==0)
printf("%4s", "-");
else
printf("%4d", G.edges[i][j].adj);
}
}
printf("/n/t/t-----------------------------------------------/n");
}
/************* Initial in-degree of all vertexes **************/
void FindInDegree(MGraph G) {
int i,j;
for(j=1; j<=G.vexNum; j++) {
Indegree[j]=0;
for(i=1; i<=G.vexNum; i++){
if(G.edges[i][j].adj==1)
Indegree[j]++;
}
}
}
/************* Print the Topological Ordering **************/
void PrintTopOrdering() {
int i;
for(i=1; i<=VEX_NUM; i++)
printf("%-4d", TopOrdering[i]);
}
/************* Algorithm of Topological Sort **************/
void TopoSort(MGraph G) {
int i, j, count;
FindInDegree(G);
InitStack();
for(i=1; i<G.vexNum; i++){
if(Indegree[i]==0)
Push(i);
}
count=0;
while(!StackEmpty()){
i=Pop();
TopOrdering[count+1]=i;
count++;
for(j=1; j<=G.vexNum; j++)
if(G.edges[i][j].adj==1 && --Indegree[j]==0)
Push(j);
}
if(count!=G.vexNum)
puts("/nThe graph HAVE cycles!");
else {
printf("/nThe graph HAVE NOT cycles, and it/'s topological ordering is:/n");
PrintTopOrdering();
}
}
/**************** Run from Here *****************/
void main() {
MGraph G;
clrscr();
puts(Menu1);
puts(Menu2);
puts(Menu3);
puts(Menu4);
G=CreateDG();
PrintAdjMatrix(G);
FindInDegree(G);
TopoSort(G);
getch();
}