本博文源于浙江大学《数据结构》,姥姥讲的拓扑排序太有用了,仿佛解决了人生发展规划的难题,应该先做什么后做什么,怎样做,如何做的难题。但是博主比较菜,实现的比较慢速,只领略到姥姥的1/10的精华。但是我想先把上课的先实现一边再说!
姥姥上课讲的是这个图片:
而我比较菜,实现的缩减版,是这张图。
因为图片仅供参考具体以代码为准,代码运行效果如下:
看起来不错的感觉,那就放上代码吧!不,先放上测试用例,这是有向图带权值为1的图模型,希望大家注意!
15 14
0 2
1 2
1 12
2 6
6 11
6 9
6 10
7 8
8 9
8 10
9 13
3 4
4 5
5 14
然后大家懂的,附上源码:
//图的邻接表创建
#include<stdio.h>
#include<stdlib.h>
#define ERROR -1
#define MaxVertexNum 20
#define true 1
#define false 0
typedef int Vertex;
typedef int WeightType;
typedef char DataType;
typedef int bool;
typedef struct ENode *PtrToENode;
struct ENode {
Vertex V1, V2;
WeightType Weight;
};
typedef PtrToENode Edge;
typedef struct AdjVNode *PtrToAdjVNode;
struct AdjVNode {
Vertex AdjV; // 邻接点的下标
WeightType Weight;//边的权重
PtrToAdjVNode Next;
};
typedef struct Vnode{
PtrToAdjVNode FirstEdge;
DataType Data;//存顶点得数据
}AdjList[MaxVertexNum];
typedef struct GNode *PtrToGNode;
struct GNode {
int Nv;//顶点数
int Ne;//边数
AdjList G;//邻接表
};
typedef PtrToGNode LGraph;
LGraph CreateGraph(int VertexNum)
{
Vertex V;
LGraph Graph;
Graph = (LGraph)malloc(sizeof(struct GNode));
Graph->Nv = VertexNum;
Graph->Ne = 0;
for(V = 0;V<Graph->Nv;V++){
Graph->G[V].FirstEdge = NULL;
Graph->G[V].Data = V ;
}
return Graph;
}
void InsertEdge(LGraph Graph, Edge E)
{
PtrToAdjVNode NewNode;
NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
NewNode->AdjV = E->V2;
NewNode->Weight = E->Weight;
//将v2插入v1的表头
NewNode->Next = Graph->G[E->V1].FirstEdge;
Graph->G[E->V1].FirstEdge = NewNode;
}
LGraph BuildGraph()
{
LGraph Graph;
Edge E;
Vertex V;
int Nv,i;
scanf("%d",&Nv);//读入顶点个数
Graph = CreateGraph(Nv);//初始化有Nv个顶点但没有边的图
scanf("%d",&(Graph->Ne));
if(Graph->Ne != 0)
{
E = (Edge)malloc(sizeof(struct ENode));
for(i=0;i<Graph->Ne;i++)
{
scanf("%d %d",&E->V1,&E->V2);
E->Weight = 1;
InsertEdge(Graph, E);
}
}
return Graph;
}
typedef int Position;
typedef int ElementType;
struct QNode{
ElementType *Data;
int rear;
int front;
int MaxSize;
};
typedef struct QNode *Queue;
Queue CreateQueue(int MaxSize){
Queue Q = (Queue)malloc(sizeof(struct QNode));
Q->Data = (ElementType *) malloc(MaxSize * sizeof(ElementType));
Q->front = Q->rear = 0;
Q->MaxSize = MaxSize;
return Q;
}
int IsFullQ(Queue Q){
return ((Q->rear+1)%Q->MaxSize == Q->front);
}
void AddQ(Queue Q,ElementType item){
if(IsFullQ(Q)){
printf("Queue is full\n");
return ;
}
Q->rear = (Q->rear+1) %Q->MaxSize;
Q->Data[Q->rear] = item;
}
int IsEmptyQ(Queue Q){
return (Q->front == Q->rear);
}
ElementType DeleteQ(Queue Q){
if(IsEmptyQ(Q))
{
printf("Queue is empty\n");
return ERROR;
}else{
Q->front = (Q->front+1)%Q->MaxSize;
return Q->Data[Q->front];
}
}
bool TopSort( LGraph Graph, Vertex TopOrder[] )
{ /* 对Graph进行拓扑排序, TopOrder[]顺序存储排序后的顶点下标 */
int Indegree[MaxVertexNum], cnt;
Vertex V;
PtrToAdjVNode W;
Queue Q = CreateQueue( Graph->Nv );
/* 初始化Indegree[] */
for (V=0; V<Graph->Nv; V++)
Indegree[V] = 0;
/* 遍历图,得到Indegree[] */
for (V=0; V<Graph->Nv; V++)
for (W=Graph->G[V].FirstEdge; W; W=W->Next)
Indegree[W->AdjV]++; /* 对有向边<V, W->AdjV>累计终点的入度 */
/* 将所有入度为0的顶点入列 */
for (V=0; V<Graph->Nv; V++)
if ( Indegree[V]==0 )
AddQ(Q, V);
/* 下面进入拓扑排序 */
cnt = 0;
while( !IsEmptyQ(Q) ){
V = DeleteQ(Q); /* 弹出一个入度为0的顶点 */
TopOrder[cnt++] = V; /* 将之存为结果序列的下一个元素 */
/* 对V的每个邻接点W->AdjV */
for ( W=Graph->G[V].FirstEdge; W; W=W->Next )
if ( --Indegree[W->AdjV] == 0 )/* 若删除V使得W->AdjV入度为0 */
AddQ(Q, W->AdjV); /* 则该顶点入列 */
} /* while结束*/
if ( cnt != Graph->Nv )
return false; /* 说明图中有回路, 返回不成功标志 */
else
return true;
}
int main()
{
LGraph Graph = BuildGraph();
int Nv = Graph->Nv;
printf("\n\n\n");
int TopOrder[Nv];
TopSort(Graph, TopOrder );
for(int i=0;i<Nv;i++)
printf("%d ",TopOrder[i]);
return 0;
}