拓扑排序算法:
1、将入度为0的顶点输出
2、将该顶点所有的后继顶点的入度减1
重复以上两步直到输出所有顶点或者找不到入度为0的顶点为止。用Indegree[]数组来记录各顶点的入度。当同时有多个入度为0的顶点时,它们的输出顺序取决与算法的实现方式,既可以用栈的方式也可以用队列的方式,本文使用栈的方式实现拓扑排序。
拓扑排序代码实现
void TopologicalSort(ALGraph G){
int indegree[MAX_VERTEX_NUM];
int i,n,count=0,k;
ArcNode *p;
SqStack S;
FindInDegree(G,indegree);
InitStack(S);
//将入度为0的顶点入栈,是顶点的下标入栈
for(i=0;i<G.vexnum;i++){
if(indegree[i]==0)Push(S,i);
}
printf("拓扑序列为:");
while(!StackEmpty(S)){
Pop(S,n);
printf("%s\t",G.vertexs[n].data);
count++;//标记输出的顶点
for(p=G.vertexs[n].firstarc;p!=NULL;p=p->nextarc){
k=p->adjvex;//获取p后继顶点下标
//减去后继顶点的入度
if(!(--indegree[k]))Push(S,k);
}
}
printf("\n");
if(count<G.vexnum)printf("有向图中有回路");
}
将各顶点的入度放入数组中
void FindInDegree(ALGraph G,int *indegree){
ArcNode *p;
int i,k;
for(i=0;i<G.vexnum;i++)indegree[i]=0;
for(i=0;i<G.vexnum;i++){
p=G.vertexs[i].firstarc;
while(p){
k=p->adjvex;
indegree[k]++;
p=p->nextarc;
}
}
}
附上完整代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define ERROR -1
#define OK 1
#define MAX_VERTEX_NUM 20
#define MAXSIZE 100
#define TRUE 1
#define FALSE 0
typedef int InfoType;
typedef struct ArcNode{
int adjvex;
struct ArcNode *nextarc;
InfoType *info;
}ArcNode;
typedef char VertexType[MAX_VERTEX_NUM];
typedef struct VNode{
VertexType data;
ArcNode *firstarc;
}VNode;
typedef struct{
VNode vertexs [MAX_VERTEX_NUM];
int vexnum,arcnum;
}ALGraph;
//构造顺序栈
typedef struct{
int data[MAXSIZE];
int top;
}SqStack;
//初始化栈
int InitStack(SqStack &S){
S.top=-1;
return OK;
}
//判栈空
int StackEmpty(SqStack S){
return(S.top==-1?TRUE:FALSE);
}
//判栈满
int StackFull(SqStack S){
return(S.top==MAXSIZE-1?TRUE:FALSE);
}
//进栈
int Push(SqStack &S,int e){
if(StackFull(S))return ERROR;
S.top++;
S.data[S.top]=e;
return OK;
}
//出栈
int Pop(SqStack &S,int &e){
if(StackEmpty(S))return ERROR;
e=S.data[S.top];
S.top--;
return OK;
}
//获取顶点的下标
int GetIndex(ALGraph G,VertexType v){
int i,k=-1;
for(i=0;i<G.vexnum;i++){
if(strcmp(G.vertexs[i].data,v)==0)k=i;
}
if(k==-1)return ERROR;
else return k;
}
//构造图
void CreateGraph(ALGraph &G){
int i;
VertexType vi,vj;
ArcNode *p,*s,*r;
printf("请输入图的顶点数和边(弧)数:");
scanf("%d%d",&G.vexnum,&G.arcnum);
//创建头结点
printf("请输入顶点的值:");
for(i=0;i<G.vexnum;i++){
scanf("%s",&G.vertexs[i].data);//输入结点的值
G.vertexs[i].firstarc=NULL;
}
//创建各结点的单链表
//头插法
for(i=0;i<G.arcnum ;i++){
printf("请输入构成第%d个弧的两个顶点:",i+1);
scanf("%s%s",&vi,&vj);
//p=new ArcNode;
//p->adjvex=GetIndex(G,vj);//adjvex为vj的下标
//p->nextarc=G.vertexs[GetIndex(G,vi)].firstarc;
//G.vertexs[GetIndex(G,vi)].firstarc=p;
//尾插法
s=new ArcNode;//每次都更新一下
s->adjvex=GetIndex(G,vj);
s->nextarc=NULL;
p=G.vertexs[GetIndex(G,vi)].firstarc;
if(p==NULL){
//vi的第一个结点
G.vertexs[GetIndex(G,vi)].firstarc=s;
}
else{
//先找到最后一个结点
while(p){
r=p;
p=p->nextarc;
}
r->nextarc=s;
}
}
}
//将各顶点的入度放入数组中
void FindInDegree(ALGraph G,int *indegree){
ArcNode *p;
int i,k;
for(i=0;i<G.vexnum;i++)indegree[i]=0;
for(i=0;i<G.vexnum;i++){
p=G.vertexs[i].firstarc;
while(p){
k=p->adjvex;
indegree[k]++;
p=p->nextarc;
}
}
}
//以邻接表的形式输出
void PrinAL(ALGraph G){
ArcNode *p;
int i;
for(i=0;i<G.vexnum;i++){
printf("%s-->",G.vertexs[i].data);
p=G.vertexs[i].firstarc;
while(p!=NULL){
printf("%d-->",p->adjvex);
p=p->nextarc;
}
if(p==NULL){
printf("NULL");
}
printf("\n");
}
}
//拓扑排序
void TopologicalSort(ALGraph G){
int indegree[MAX_VERTEX_NUM];
int i,n,count=0,k;
ArcNode *p;
SqStack S;
FindInDegree(G,indegree);
InitStack(S);
//将入度为0的顶点入栈,是顶点的下标入栈
for(i=0;i<G.vexnum;i++){
if(indegree[i]==0)Push(S,i);
}
printf("拓扑序列为:");
while(!StackEmpty(S)){
Pop(S,n);
printf("%s\t",G.vertexs[n].data);
count++;//标记输出的顶点
for(p=G.vertexs[n].firstarc;p!=NULL;p=p->nextarc){
k=p->adjvex;//获取p后继顶点下标
//减去后继顶点的入度
if(!(--indegree[k]))Push(S,k);
}
}
printf("\n");
if(count<G.vexnum)printf("有向图中有回路");
}
int main(){
ALGraph G;
CreateGraph(G);
PrinAL(G);
TopologicalSort(G);
return OK;
}