【数据结构/C语言版】【图】拓扑排序

拓扑排序

拓扑排序是对图结点关系进行的排序,其排序结果提供了一种无后效性的遍历图的方式,即:后续结点不会影响之前的结点。此性质可用于动态规划、关键路径等。
进行拓扑排序需要注意:1、需要了解图的度(入度与出度) 2、只有有向无环图才有拓扑序列。

入度出度

入度:当前结点入边的条数。
求入度时只需要遍历图,将所有出边的目标点入度indegree[v]++;

Status FindInDegree(ALGraph G, int* indegree)//求入度
{
	for (int i = 0; i < G.vexnum; i++) {
		ArcNode* p = G.vertices[i].firstarc->nextarc;
		while (p != NULL) {
			indegree[p->adjvex]++;
			p = p->nextarc;
		}
	}
	return 1;
}

出度:当前结点出边的条数。
结点的度:入度+出度等于结点的度。
易发现,如果每一个结点的入边作为限制此结点的条件的话,入度为零的点表示没有结点是此结点的先决条件。另外,此结点入度为零时表示此结点可顺利完成,那么此结点所影响结点入度应该减一。如果有环,则自己的先决条件是自己矛盾。

排序过程

将入度为零的结点放入一种存储结构(栈或队列)中,每次从存储结构中取出一个结点,将其能够直达的所有结点入度减一,若此时入度为零将则其加入存储结构,如此反复直至存储结构为空。

#define SElemType int
typedef struct SNode {
	SElemType data;
	SNode* next;
}SNode, * LinkStack;

Status InitStack(LinkStack& S)
{
	S = (LinkStack)malloc(sizeof(SNode));
	if (!S)
		return 0;
	S->next = NULL;
}

Status DestroyStack(LinkStack& S)
{
	LinkStack p = S->next, ptmp;
	while (p) {
		ptmp = p->next;
		free(p);
		p = ptmp;
	}
	free(S);
	return 1;
}

Status ClearStack(LinkStack& S)
{
	LinkStack p = S->next, ptmp;
	while (p) {
		ptmp = p->next;
		free(p);
		p = ptmp;
	}
	S->next = NULL;
	return 1;
}

Status StackEmpty(LinkStack& S)
{
	return S->next == NULL;
}

int StackLength(LinkStack S)
{
	int ans = 0;
	LinkStack p = S->next;
	while (p) {
		ans++;
		p = p->next;
	}
	return ans;
}

Status GetTop(LinkStack S, SElemType& e)
{
	if (S->next == NULL)
		return 0;
	e = S->next->data;
	return 1;
}

Status Push(LinkStack& S, SElemType e)
{
	SNode* p = (SNode*)malloc(sizeof(SNode));
	p->data = e;
	p->next = S->next;
	S->next = p;
	return 1;
}

Status Pop(LinkStack& S, SElemType& e)
{
	if (S->next == NULL)
		return 0;
	e = S->next->data;
	SNode* p = S->next;
	S->next = p->next;
	free(p);
	return 1;
}

Status visit(SElemType e)
{
	cout << e << endl;
	return 1;
}

基于邻接表

测试数据:

0
6 8
v1 v2 v3 v4 v5 v6
v1 v3
v1 v2
v2 v4
v2 v5
v5 v6
v4 v6
v3 v4
v3 v6

测试输出:

0 v1
2 v3
1 v2
3 v4
4 v5
5 v6

代码:

//求入度 
Status FindInDegree(ALGraph G, int* indegree)
{
	for (int i = 0; i < G.vexnum; i++) {
		ArcNode* p = G.vertices[i].firstarc->nextarc;
		while (p != NULL) {
			indegree[p->adjvex]++;
			p = p->nextarc;
		}
	}
	return 1;
}

//拓扑排序 
Status TopologicalOrder(ALGraph G)
{
	int indegree[MAX_VERTEX_NUM] = { 0 };
	FindInDegree(G, indegree);//求入度
	LinkStack S;
	InitStack(S);
	int i, count = 0;
	for(i=0;i<G.vexnum;i++){
		if (!indegree[i])
			Push(S, i);
	}
	while (!StackEmpty(S))
	{
		Pop(S, i);
		cout << i << ' ' << G.vertices[i].data << endl;
		count++;
		ArcNode* p = G.vertices[i].firstarc->nextarc;
		while (p != NULL) {
			int v = p->adjvex;
			if (!(--indegree[v])) Push(S, v);
			p = p->nextarc;
		}
	}
	if (count < G.vexnum)
		return ERROR;
	return 1;
}

你可能感兴趣的:(数据结构,算法,数据结构,图,拓扑排序)