[Data structure] Topological sorting of directed acyclic graph (AOV-net) (C language)

1. Topological sequence

A directed acyclic graph is a directed graph without cycles. Directed acyclic graphs can be used to describe the process of a project or system, such as a construction drawing of a project, a graph of constraints between courses for students, etc.
A directed acyclic graph that uses vertices to represent activities and arcs to represent the priority relationship between activities is called a vertex-represented activity network , or AOV-net for short .
Topological sequence : In a directed graph G = (V, {E}), the linear sequence (v1, v2, v3, ..., vn) of vertices in V is called a topological sequence. If this sequence satisfies the condition: for any two vertices vi and vj in the sequence, there is a path from vi to vj in G, then vi must be arranged before vj in the sequence.
topological sequence
The characteristics of AOV-net :
① If vi is the preceding activity of vj, and vj is the preceding activity of vk, then vi must be the preceding activity of vk, that is, the preceding relationship is transitive.
The topological sequence of AOV-net is not unique . Another topological sequence of the directed acyclic graph shown above is: C1, C2, C3, C8, C4, C5, C9, C7, C6. The basic idea of
​​topological sorting (Topological Sort) : ① Select a node output without predecessor from the directed graph; ② Delete this node and the edge starting from it; ③ Repeat ① and ② until there is no predecessor ④ If the number of output nodes is less than the number of vertices in the directed graph at this time, it means that there are loops in the directed graph, otherwise the order of the output vertices is a topological sequence. Example :





Implementation process

2. Implementation of topological sorting (taking the adjacency list as an example)

2.1 Basic idea

A vertex with an in-degree of 0 is a vertex without a predecessor. For the adjacency list structure, an array indegree[] can be attached to store the in-degree of each vertex, so: ① Find the node without a predecessor in G——find indegree[i]
as 0’s vertex i;
② Delete all arcs starting from i——for all adjacent vertex k behind the vertex i, the corresponding degree[k] will be decremented by 1; (Note:
If the storage structure is an adjacency matrix, then
① Find the nodes without predecessors in G - find the columns with all 0 values ​​in the adjacency matrix;
② Delete all arcs starting from i - set all the rows corresponding to i in the matrix to 0;)

In order to avoid repeated detection of vertices whose in-degree is 0, an auxiliary stack can be set up. If the in-degree of a vertex is reduced to 0, it will be pushed into the stack. Whenever a vertex is output, it will be deleted from the stack. That is, pop the stack.

2.2 Complete implementation of code and running results

# include<stdio.h>
# include<malloc.h>
# define MAX_VERTEX_NUM 20
# define TRUE 1
# define FALSE 0

/*图的邻接表表示法*/
typedef char VertexData;
//弧结点结构
typedef struct ArcNode {
    
    
	int adjvex;								//该弧指向顶点的位置
	struct ArcNode* nextarc;				//指向下一条弧的指针
}ArcNode;
//表头结点结构
typedef struct VertexNode {
    
    
	VertexData data;						//顶点数据
	ArcNode* firstarc;						//指向该顶点的第一条弧的指针
}VertexNode;
//邻接表结构
typedef struct {
    
    
	VertexNode vertex[MAX_VERTEX_NUM];
	int vexnum, arcnum;						//图的顶点数和弧数
}AdjList;

/*求顶点位置*/
int LocateVertex(AdjList* G, VertexData v) {
    
    
	int k;
	for (k = 0; k < G->vexnum; k++) {
    
    
		if (G->vertex[k].data == v)
			break;
	}
	return k;
}

/*创建有向图的邻接表*/
int CreateAdjList(AdjList* G) {
    
    
	int i, j, k;
	VertexData v1, v2;
	ArcNode* p;
	printf("输入图的顶点数和弧数:");				//输入图的顶点数和弧数
	scanf("%d%d", &G->vexnum, &G->arcnum);
	printf("输入图的顶点:");
	for (i = 0; i < G->vexnum; i++) {
    
    			//输入图的顶点,初始化顶点结点
		scanf(" %c", &(G->vertex[i].data));
		G->vertex[i].firstarc = NULL;
	}
	for (k = 0; k < G->arcnum; k++) {
    
    
		printf("输入第%d条弧的两个顶点:", k + 1);
		scanf(" %c %c", &v1, &v2);				//输入一条弧的两个顶点
		i = LocateVertex(G, v1);
		j = LocateVertex(G, v2);
		p = (ArcNode*)malloc(sizeof(ArcNode));	//申请新弧结点
		p->adjvex = j;
		p->nextarc = G->vertex[i].firstarc;
		G->vertex[i].firstarc = p;
	}
}

/*顺序栈的存储结构,辅助栈*/
typedef struct {
    
    
	int elem[MAX_VERTEX_NUM];			//用于存放栈中元素的一维数组
	int top;							//存放栈顶元素的下标,top为-1表示空栈
}SeqStack;

/*初始化顺序栈*/
void InitStack(SeqStack* S) {
    
    
	S->top = -1;
}

/*判空*/
int IsEmpty(SeqStack* S) {
    
    
	if (S->top == -1)					//栈为空
		return TRUE;
	else
		return FALSE;
}

/*顺序栈进栈*/
int Push(SeqStack* S, int x) {
    
    
	if (S->top == MAX_VERTEX_NUM - 1)	//栈已满
		return FALSE;
	S->top++;
	S->elem[S->top] = x;				//x进栈
	return TRUE;
}

/*顺序栈出栈*/
int Pop(SeqStack* S) {
    
    
	if (S->top == -1)					//栈为空
		return FALSE;
	S->top--;
	return TRUE;
}

int indegree[MAX_VERTEX_NUM];			//存放各顶点入度

/*求各顶点入度算法*/
void FindID(AdjList G) {
    
    
	int i;
	ArcNode* p;
	for (i = 0; i < G.vexnum; i++)
		indegree[i] = 0;
	for (i = 0; i < G.vexnum; i++) {
    
    
		p = G.vertex[i].firstarc;
		while (p != NULL) {
    
    
			indegree[p->adjvex]++;
			p = p->nextarc;
		}
	}
}

/*拓扑排序算法*/
int TopoSort(AdjList G) {
    
    
	int i, count = 0, k;
	SeqStack S;
	ArcNode* p;
	FindID(G);							//求各顶点入度
	InitStack(&S);						//初始化辅助栈
	for (i = 0; i < G.vexnum; i++) {
    
    
		if (indegree[i] == 0)
			Push(&S, i);				//将入度为0的顶点入栈
	}
	while (!IsEmpty(&S)) {
    
    
		i = S.elem[S.top];
		Pop(&S);
		printf("%c ", G.vertex[i]);
		count++;
		p = G.vertex[i].firstarc;
		while (p != NULL) {
    
    
			k = p->adjvex;
			indegree[k]--;				//i号顶点的每个邻接点的入度减1
			if (indegree[k] == 0)
				Push(&S, k);			//若入度减为0则入栈
			p = p->nextarc;
		}
	}
	if (count < G.vexnum) {
    
    
		printf("该图存在回路!\n");
		return FALSE;
	}
	else
		return TRUE;
}

int main() {
    
    
	AdjList G;
	CreateAdjList(&G);
	printf("\n拓扑排序:");
	TopoSort(G);
	return 0;
}

Operation results
operation result
Reference: Geng Guohua "Data Structure - Described in C Language (Second Edition)"

For more data structure content, follow my "Data Structure" column : https://blog.csdn.net/weixin_51450101/category_11514538.html?spm=1001.2014.3001.5482

Guess you like

Origin blog.csdn.net/weixin_51450101/article/details/123018532
Recommended