拓扑排序
Posted zcxhaha
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了拓扑排序相关的知识,希望对你有一定的参考价值。
拓扑排序
1.存储结构
? 采用邻接表,在表节点中增加degree域,记录每个节点的入度。
2.实现步骤
? 1.先求每个节点的入度
? 2.借助栈,扫描一遍表,将入度为0的节点入栈
? 3.依次将栈中的节点出栈,每次出栈都将该节点的邻接点的入度减一(删去该点及以该点为尾的弧)
? 4.设置一个计数器,记录出栈节点的个数,如果全部出栈后,计数器的值等于图的顶点的个数,表明该图无环。
3.实现代码:
#include<stdio.h>
#include<stdlib.h>
#define MAX_VERTEX_NUM 20
#define STACK_INIT_SIZE 100 //最大容量
#define STACKINCREMENT 10 //动态增量
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR -1
#define OVERFLOW -1
typedef char VertexType;
typedef int Status; //函数的状态
/*-----------图的存储结构-----------*/
//弧结点
typedef struct ArcNode{
int adjvex; //该弧所指向的顶点的位置
int value;
struct ArcNode *nextarc; //指向下一条弧
}ArcNode;
//表节点
typedef struct VNode{
int degree; //顶点的入度
VertexType data; //顶点信息
ArcNode * firstchild; //指向第一条以自己为弧尾弧
}VNode, AdjList[MAX_VERTEX_NUM];
//邻接表
typedef struct{
AdjList vertices;
int vexnum, arcnum;
}ALGraph;
/*----------------------------------*/
typedef VNode ElemType; //数据元素的类型 注意使用宏定义的好处
/*-----------栈的存储结构-----------*/
typedef struct
{
ElemType * base; //栈底
ElemType * top; //栈顶
int stacksize; //栈的当前已分配的空间
}SqStack;
/*---------------------------------*/
/*--------------------------栈的基本操作--------------------------*/
/*初始化空栈*/
Status InitStack(SqStack * S)
{
S->base = S->top = (ElemType *)malloc(STACK_INIT_SIZE * sizeof(ElemType));
if (!S->base)
{
return FALSE;
}
S->stacksize = STACK_INIT_SIZE;
return TRUE;
}
/*入栈*/
Status Push(SqStack * S, ElemType e)
{
/*判断是否栈满*/
if(S->top - S->base >= S->stacksize)
{
S->base = (ElemType *)realloc(S->base, (STACKINCREMENT+S->stacksize) * sizeof(ElemType));
if (S->base == NULL)
{
printf("内存分配失败!
");
return ERROR;
}
S->top = S->base + S->stacksize;
S->stacksize = STACKINCREMENT+S->stacksize;
}
*(S->top) = e;
S->top++;
}
/*出栈*/
Status Pop (SqStack * S, ElemType * e)
{
if(S->base == S->top)
{
return ERROR;
}
(*e) = *(--(S->top));
return OK;
}
/*判断是否为空栈*/
Status StackEmpty(SqStack * S)
{
if (S->base == S->top)
{
return TRUE;
}
else
{
return FALSE;
}
}
/*--------------------------------------------------------------------*/
//创建有向网
Status Creat_AlGraph(ALGraph &G)
{
int vexnum, arcnum;
int i;
int c;
int head, tail, value; //弧头,弧尾,权值
ArcNode * p;
for(i = 0; i < MAX_VERTEX_NUM; ++i)
{
G.vertices[i].firstchild = NULL;
}
printf("请输入顶点的个数和弧的个数:
");
scanf("%d%d", &vexnum, &arcnum);
G.arcnum = arcnum;
G.vexnum = vexnum;
printf("请依次输入个顶点:
");
for(i = 0; i < vexnum; ++i)
{
getchar();
scanf("%c", &c);
G.vertices[i].data = c;
}
printf("请依次输入各条弧(位置为在邻接表中的位置)的信息:
");
for(i = 0; i < arcnum; ++i)
{
// scanf("%d%d%d", &head, &tail, &value);
scanf("%d%d", &head, &tail);
p = (ArcNode *)malloc(sizeof(ArcNode));
if(!p)
{
exit(OVERFLOW);
}
p->value = value;
p->adjvex = tail;
//头插
p->nextarc = G.vertices[head].firstchild;
G.vertices[head].firstchild = p;
}
return OK;
}
//初始化各节点的入度
Status InitInDegree(ALGraph &G)
{
ArcNode *p = NULL;
int i;
//先清零
for(i = 0; i < G.vexnum; ++i)
{
G.vertices[i].degree = 0;
}
//求入度
for(i = 0; i < G.vexnum; ++i)
{
p = G.vertices[i].firstchild;
while(p)
{
G.vertices[p->adjvex].degree++;
p = p->nextarc;
}
}
return OK;
}
//拓扑排序
Status TopologicalSort(ALGraph &G)
{
SqStack S;
VNode e;
ArcNode *p = NULL;
int i; //循环变量
int count = 0; //计数器
InitStack(&S);
InitInDegree(G);
//将度为0的节点入栈
for(i = 0; i < G.vexnum; ++i)
{
if(G.vertices[i].degree == 0)
{
Push(&S, G.vertices[i]);
}
}
while(!StackEmpty(&S))
{
Pop(&S, &e);
count++;
printf("%c ", e.data);
p = e.firstchild;
while(p)
{
if(!(--G.vertices[p->adjvex].degree))
{
Push(&S, G.vertices[p->adjvex]);
}
p = p->nextarc;
}
}
if(count < G.vexnum)
{
return ERROR;
}
else
{
return OK;
}
}
int main(void)
{
ALGraph G;
Creat_AlGraph(G);
TopologicalSort(G);
return 0;
}
//测试数据
/*
A B C D E F G H I J K L
0 3
0 1
0 2
0 11
1 2
2 4
2 6
2 7
3 4
4 6
5 7
8 9
8 10
8 11
9 11
10 5
*/
以上是关于拓扑排序的主要内容,如果未能解决你的问题,请参考以下文章