1. 程式人生 > >[圖] 7.1 拓撲排序|拓撲序列

[圖] 7.1 拓撲排序|拓撲序列

【測試資料】 【結果】 在這裡插入圖片描述

【資料結構】鄰接表為例 需要將鄰接表的資料結構加上一個count,表示入度

typedef struct VNode{
	char data;
	int count; //入度
	ArcNode *firstarc; //第一條邊
}VNode, AdjList[MAX_VERTEX_NUM];

【程式碼】

//計算每個頂點的入度
void CntGraphIndegree(ALGraph *pG) {
	ArcNode *p;
	int i;
	for (i=0; i<pG->vernum; i++) {
		for (p=pG->vers[i].firstarc;
p; p=p->next) { pG->vers[p->adjV].count++; } } } // 拓撲排序,並列印拓撲序列 int TopSort(ALGraph *pG) { int i,j; int n=0; int stack[maxSize],top=-1; //儲存當前所有入度為0的頂點 ArcNode *p; CntGraphIndegree(pG); //計算入度 //將入度為0的頂點壓入棧中 for (i=0; i<pG->vernum; i++) { if (pG->vers[i].count==0) stack[++top]
=i; } while (top!=-1) { i = stack[top--]; //頂點出棧,等效於在圖中刪掉 ++n; printf("%c ", pG->vers[i].data); p=pG->vers[i].firstarc; while (p!=NULL) { j = p->adjV; --(pG->vers[j].count); if (pG->vers[j].count==0) stack[++top]=j; p=p->next; } } if (n==pG->vernum)
//拓撲排序後沒有剩餘頂點 return 1; else //拓撲排序後還有剩餘頂點 return 0; }

【完整程式碼】

#include<stdio.h>
#include<stdlib.h>

#define maxSize 50
#define MAX_VERTEX_NUM 20

#ifndef BASE
#define BASE
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
typedef int Status;
typedef int bool;
#endif

typedef struct ArcNode{
	int adjV;
	struct ArcNode *next;
}ArcNode;
typedef struct VNode{
	char data;
	int count; //入度
	ArcNode *firstarc; //第一條邊
}VNode, AdjList[MAX_VERTEX_NUM];
typedef struct{
	int vernum,arcnum;
	AdjList vers;
}ALGraph;

/*------------------------
 |建立有向圖的鄰接表     |
 ------------------------*/
Status InitGraph_AL(ALGraph *pG) { //初始化
	int i;
	pG->arcnum = 0;
	pG->vernum = 0;
	for (i=0; i<MAX_VERTEX_NUM; ++i)
		pG->vers[i].firstarc = NULL; //VC++6.0中指標初始化為0xcccccccc
	return OK;
}
int LocateVex_AL(ALGraph G, char e) { //定位值為e的元素下標
	int i;
	for (i=0; i<G.vernum; ++i) {
		if (G.vers[i].data == e) {
			return i;
		}
	}
	return -1;
}
Status CreateDG_AL(ALGraph *pG) { //建立有向圖的鄰接表--不帶權
	//輸入規則:頂點數目->弧的數目->各頂點的資訊->各條弧的資訊
	int i,a,b;
	char tmp[MAX_VERTEX_NUM];
	char h,t;
	ArcNode *p, *q;

	InitGraph_AL(pG); //VC++6.0中指標初始化為0xcccccccc,如果不將指標初始化為NULL,會出錯
	//頂點數目
	scanf("%d", &i); if (i<0) return ERROR;
	pG->vernum = i;
	//弧的數目
	scanf("%d", &i); if (i<0) return ERROR;
	pG->arcnum = i;
	//各頂點資訊
	scanf("%s", tmp);
	for (i=0; i<pG->vernum; ++i) {
		pG->vers[i].data=tmp[i];
		pG->vers[i].count=0;
	}
	//弧的資訊
	for (i=0; i<pG->arcnum; ++i) {
		scanf("%s", tmp);
		h = tmp[0]; t = tmp[2];
		a = LocateVex_AL(*pG, h);
		b = LocateVex_AL(*pG, t);
		if (a<0 || b<0) return ERROR;
		p = (ArcNode *)malloc(sizeof(ArcNode)); if (!p) exit(OVERFLOW);
		p->adjV=b;p->next=NULL;
		if (pG->vers[a].firstarc) { //已經有邊了
			for (q = pG->vers[a].firstarc; q->next; q=q->next) ; //找到最後一條
			q->next = p;
		} else { //第一條邊
			pG->vers[a].firstarc = p;
		}
	}
	return OK;
}

//計算每個頂點的入度
void CntGraphIndegree(ALGraph *pG) {
	ArcNode *p;
	int i;
	for (i=0; i<pG->vernum; i++) {
		for (p=pG->vers[i].firstarc; p; p=p->next) {
			pG->vers[p->adjV].count++;
		}
	}
}
// 拓撲排序,並列印拓撲序列
int TopSort(ALGraph *pG) {
	int i,j;
	int n=0;
	int stack[maxSize],top=-1; //儲存當前所有入度為0的頂點
	ArcNode *p;

	CntGraphIndegree(pG); //計算入度
	//將入度為0的頂點壓入棧中
	for (i=0; i<pG->vernum; i++) {
		if (pG->vers[i].count==0)
			stack[++top]=i; 
	}

	while (top!=-1) {
		i = stack[top--]; //頂點出棧,等效於在圖中刪掉
		++n;
		printf("%c ", pG->vers[i].data);

		p=pG->vers[i].firstarc;
		while (p!=NULL) {
			j = p->adjV;
			--(pG->vers[j].count);
			if (pG->vers[j].count==0)
				stack[++top]=j;
			p=p->next;
		}
	}

	if (n==pG->vernum) //拓撲排序後沒有剩餘頂點
		return 1;
	else //拓撲排序後還有剩餘頂點
		return 0;
}

int main() {
/*
測試資料:沒有迴路
9
11
ABCDEFGHI
A,D
B,D
B,E
C,E
D,F
D,G
E,H
F,I
G,E
G,I
H,I
測試資料二:有迴路
9
11
ABCDEFGHI
A,D
B,D
C,E
D,F
D,G
E,B
E,H
F,I
G,E
G,I
H,I
*/
	ALGraph G;
	int ret;

	CreateDG_AL(&G);

	ret = TopSort(&G);
	printf("\n該有向圖是否有迴路:%d\n", !ret);
	
	return 0;
}