6-5 拓扑排序 (10分)
试实现拓扑排序算法。函数void FindInDegree(ALGraph G,int indegree[])实现图中各个顶点入度的统计;函数int TopologicalSort(ALGraph G , int topo[])获取拓扑序列。
函数接口定义:
void FindInDegree(ALGraph G,int indegree[]);
int TopologicalSort(ALGraph G , int topo[]);
其中 G 是基于邻接表及逆邻接表存储表示的有向图,indegree存放个顶点的入度,topo存放拓扑序列。
裁判测试程序样例:
#include <iostream>
using namespace std;
#define MVNum 100
typedef char VerTexType;
typedef struct ArcNode{
int adjvex;
struct ArcNode *nextarc;
}ArcNode;
typedef struct VNode{
VerTexType data;
ArcNode *firstarc;
}VNode, AdjList[MVNum];
typedef struct{
AdjList vertices; //邻接表
AdjList converse_vertices;//逆邻接表
int vexnum, arcnum;
}ALGraph;
int CreateUDG(ALGraph &G);//创建图,实现细节隐藏
void FindInDegree(ALGraph G,int indegree[]);
int TopologicalSort(ALGraph G , int topo[]);
int main(){
ALGraph G;
CreateUDG(G);
int *topo = new int [G.vexnum];
if(TopologicalSort(G , topo)){
for(int j = 0 ; j < G.vexnum; j++){
if(j != G.vexnum - 1)
cout << G.vertices[topo[j]].data << ",";
else
cout << G.vertices[topo[j]].data ;
}
}
else
cout << "Ring in net";
return 0;
}
/* 请在这里填写答案 */
输入样例:
第1行输入结点数vexnum和边数arcnum。第2行输入vexnum个字符表示结点的值,接下来依次输入arcnum行,每行输入2个字符v和u,表示v到u有一条有向边。
6 9
1 2 3 4 5 6
1 2
1 3
1 4
3 2
3 5
4 5
4 3
6 4
6 5
输出样例:
输出拓扑序列。
6,1,4,3,2,5
注意事项:
因为是邻接表储存表示的有向图,所以在拓扑排序时需定义一个栈
//定义栈
typedef struct{
int *base;
int *top;
int stacksize;
}spStack;
int indegree[100]; /*用indegree存放个顶点的入度*/
spStack S;//定义栈
void InitStack(spStack &S)//初始化栈
{
S.base=new int[100];
if(!S.base)
exit(1);//退出
S.top=S.base;
S.stacksize = 100;
}
void Push(spStack &S,int i)//进栈
{
if(S.top - S.base == S.stacksize)//栈满
return;
*S.top++ = i;
}
void Pop(spStack &S , int &i)//出栈
{
if(S.top == S.base)
return;
i = *--S.top;
}
bool StackEmpty(spStack S)//栈空
{
if(S.top == S.base)
return true;
return false;
}
void FindInDegree(ALGraph G)//统计入度
{
int i;
ArcNode *p;/*p是指向边表节点的指针*/
for(i=0;i<G.vexnum;i++)/*遍历赋值*/
indegree[i]=0;
for(i=0;i<G.vexnum;i++)
{
p=G.vertices[i].firstarc;
while(p!=NULL)
{
indegree[p->adjvex]++;/*入度加一,p->adjvex是下标*/
p = p->nextarc;
}
}
}
int TopologicalSort(ALGraph G , int topo[])//拓扑排序 书上原代码
{
int i , m=0;
FindInDegree(G);
InitStack(S);/*栈S初始化*/
for(i = 0; i < G.vexnum; ++i)
if(!indegree[i])
Push(S, i); /*入度为0进栈*/
while(!StackEmpty(S))/*栈S非空*/
{
Pop(S, i);/*将栈顶顶点vi出栈*/
topo[m]=i;/*将vi保存在topo中*/
m++;
ArcNode *p = G.vertices[i].firstarc; /*p指向vi的第一个邻接点*/
while(p){
int k = p->adjvex; /*vk为vi的邻接点*/
--indegree[k]; /*vi的每个邻接点的入度减一*/
if(indegree[k] ==0) Push(S, k); /*若入度为0则入栈*/
p = p->nextarc; /*p指向顶点vi下一个邻接结点*/
}
}
if(m < G.vexnum)
return 0; /*该有向图有回路,不能拓扑排序*/
else
return 1;
}