版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/IceS2388627880/article/details/59486951
用顶点表示活动、有向边表示活动之间的先后关系的有向无环(DAG)图称为顶点活动网,简称AOV网。对于一个又向无环图DAG,若将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,<u,v>属于边的集合,若u出现在v之前,这样的线性序列称为拓扑序列。
拓扑排序
基本思想:
1.在有向图中选取入度为0的顶点,并输出。
2.从有向图中删除该顶点及其该顶点的出边。
3.重复1和2。
4.输出剩余的无前驱结点。
#if ! defined(ALGRAPH_H)
#define ALGRAPH_H
#include<stdio.h>
#include<stdlib.h>
#define MaxVertexNum 50
typedef char VertexType;
typedef struct node{
int adjvex;//顶点的序号
struct node *next;//指向下一条边的指针
}EdgeNode;
typedef struct vnode{
VertexType vertex;//顶点表示
EdgeNode *link;//第一个边
}VNode,Adjlist[MaxVertexNum];
typedef Adjlist ALGraph;//定义为图类型
/******拓扑排序******
基本思路:确定个节点的入度,取出入度为0的顶点。取出入度为0的顶点,减少相关顶点的入度。
*/
void TopuSort(ALGraph G,int n){
int inde[MaxVertexNum]={0};
int i;
int m=0;//入度为0的出栈顶点数量
int stack[20];//栈
int top=-1;
EdgeNode *p;//单边
//1.初始化进度
for(i=0;i<n;i++){
p=G[i].link;
while(p){
inde[p->adjvex]++;//邻边表中有记录就增加一次
p=p->next;
}
}
//2.进度为0的节点入栈
for(i=0;i<n;i++){
if(0 == inde[i]){
stack[++top]=i;
}
}
//3.拓扑排序
while(top!=-1){
i=stack[top--];//输出入度为0的节点
printf("%c ",G[i].vertex);//顶点的字符串
m++;
p=G[i].link;//G[i]的出度
while(p){//去掉p边,必须减掉p边目标点的入度
inde[p->adjvex]--;
if(0 == inde[p->adjvex]){//入度为0,则出栈
stack[++top]=p->adjvex;
}
p=p->next;
}
}
//4.判断排序的结果
if(m<n){
//当输出数小于顶点数时,有回路,排序失败
printf("The Graph has a cycle!");
}
}
void TopuSortTest(){
ALGraph G;
int n=6;
EdgeNode n1;
EdgeNode n2;
EdgeNode n3;
EdgeNode n4;
EdgeNode n5;
EdgeNode n6;
EdgeNode n7;
G[0].vertex='a';
G[1].vertex='b';
G[2].vertex='c';
G[3].vertex='d';
G[4].vertex='e';
G[5].vertex='f';
//a
n1.adjvex=1;//b
n2.adjvex=3;//d
n2.next=NULL;
n1.next=&n2;
G[0].link=&n1;
//b
n3.adjvex=4;//e
n3.next=NULL;
G[1].link=&n3;
//c
n4.adjvex=1;//b
n4.next=&n5;
n5.adjvex=5;//f
n5.next=NULL;
G[2].link=&n4;
//d
n6.adjvex=4;//e
n6.next=NULL;
G[3].link=&n6;
//e
G[4].link=NULL;
//f
n7.adjvex=4;//e
n7.next=NULL;
G[5].link=&n7;
TopuSort(G,n);
printf("\n\n");
}
int main(){
TopuSortTest();
return 0;
}
#endif
该文件的后缀建议为.c!