1. 程式人生 > >關於鄰接表的拓撲排序

關於鄰接表的拓撲排序

演算法思想如下:

利用鄰接表儲存圖,先設一個輔助陣列indegree[]來計算所有節點的入度;首先把入度為零的節點入棧,當棧不為空時,把棧中的元素出棧,然後刪除輸出元素為弧尾的所有弧,並判斷相應節點的入度是否為零,為零,則壓入棧中。重複執行,直到棧空。

#include <stdio.h>
#include <stdlib.h>
#define MAX 30

int indegree[MAX];//用來儲存所有節點的入度之和

typedef struct ArcNode{
	struct ArcNode *nextarc;
	int adjvex;
}ArcNode;
typedef struct{
	ArcNode *firstarc;
	char data;
}VNode,Vertice[MAX];
typedef struct{
	int vexnum,arcnum;
	Vertice vex;
}ALGraph;
typedef struct{
	int top;
	int *base;
	int stacksize;
}SqStack;

int LocateVex(ALGraph G, char v){
	for(int i = 0; i < G.vexnum; i ++){
		if(v == G.vex[i].data)
			return i;
	}
	
	return -1;
}

void CreateALGraph(ALGraph &G){
	int i,j,k;
	char v1,v2;
	ArcNode *p,*s;
	
	printf("輸入節點和邊的數目:\n");
	scanf("%d%d",&G.vexnum,&G.arcnum);
	
	printf("輸入結點:\n");
	getchar();
	for(i = 0; i < G.vexnum; i ++){
		scanf("%c",&G.vex[i].data);
		G.vex[i].firstarc = NULL;	
	}
	
	printf("輸入各條邊:\n");
	for(i = 0; i < G.arcnum; i ++){
		getchar();
		scanf("%c%c",&v1,&v2);
		
		j = LocateVex(G,v1);	k = LocateVex(G,v2);
		
		s = (ArcNode *)malloc(sizeof(ArcNode));
		s->adjvex = k;		s->nextarc = NULL;
		
		
		if(!G.vex[j].firstarc){
			G.vex[j].firstarc = s;
		}
		else{
			p = G.vex[j].firstarc;
			
			while(p->nextarc)
				p = p->nextarc;
			
			p->nextarc = s;
		}
	}
}

void FindInputDgeree(ALGraph G){//計算所有節點的入度
	ArcNode *p;
	int i;
	
	for(i = 0; i < G.vexnum; i ++)
		indegree[i] = 0;
	
	for(i = 0; i < G.vexnum; i ++){
		p = G.vex[i].firstarc;
		
		while(p){
			indegree[p->adjvex] ++;
			p = p->nextarc;
		}
	}
}

void InitStack(SqStack &S){
	S.base = (int *)malloc(sizeof(int) * MAX);
	
	if(!S.base)
		return ;
	
	S.top = 0;
	S.stacksize = MAX;
}

void Push(SqStack &S, int i){
	if(S.top >= S.stacksize){
		S.base = (int *)realloc(S.base,(S.top + MAX) * sizeof(int));
		
		if(!S.base)
			return ;
		
		S.stacksize += MAX;
	}
	
	S.base[S.top ++] = i;
}

int StackEmpty(SqStack S){
	if(!S.top )
		return 1;
	
	return 0;
}

void Pop(SqStack &S, int &i){
	if(!S.top)
		return;
	
	i = S.base[-- S.top];
}

void TopologicalSort(ALGraph G){
	FindInputDgeree(G);
	int count = 0,i;
	SqStack S;		ArcNode *p;
	InitStack(S);
	
	for(i = 0; i < G.vexnum; i ++)
		if(!indegree[i])//把入度為零的節點入棧
			Push(S,i);
	
	printf("拓撲序列如下:\n");		
	while(!StackEmpty(S)){
		Pop(S,i);
		printf("%c\n",G.vex[i].data);	count ++;
		
		p = G.vex[i].firstarc;
		
		while(p){		
			if(!(-- indegree[p->adjvex]))//判斷去掉一條邊後節點的入度是否為零
				Push(S,p->adjvex);
			
			p = p->nextarc;
		}		
	}
	
	if(count < G.vexnum)
		printf("該圖為有向有環圖\n");
}

int main(){
	ALGraph G;
	
	CreateALGraph(G);//建立圖	
	
	TopologicalSort(G);//進行拓撲排序

	return 0;
}