Topological sort Topological Sort

Introduction to AOV Network

In a directed graph representing a project , vertices are used to represent activities, and arcs are used to represent the priority relationship between activities. Such a directed graph is a network where vertices represent activities. We call it AOV network (Activity On Vertex Network). As shown in the
figure :
insert image description here
Let G(V,E) be a directed graph with n vertices, the vertex sequence v1, v2,...vn in V, if there is a path from vertex vi to vj , then the vertex vi in ​​the vertex sequence must between vertices vj. Then we call such a sequence of vertices a topological sequence.

topological sort

Topological sorting is the process of constructing a topological sequence for a directed graph .
When constructing, there are two outcomes

  1. If all the vertices of this network are output, it means that it is an AOV network without rings (loops);
  2. If the number of output fixed points is less, even if one is missing, it means that there is a loop in this network, not an AOV network.

Topological Sort Algorithm

The basic idea of ​​constructing topological sorting for the AOV network is: select a vertex output with an in-degree of 0 from the AOV network, then delete this vertex, and delete the arc tailed by this vertex , and continue to repeat this step until all vertices are output or Until there is no vertex with an in-degree of 0 in the AOV network.
Applicable data structure for topological sorting: adjacency list (easy to delete nodes)
insert image description here
in stores degree, data stores data, firstedge points to the next element

lift chestnut

As shown in the figure, an AOV graph is given with
insert image description here
its adjacency list structure
insert image description here
. Let’s first look at the structure code of the adjacency matrix:

/*邻接矩阵结构*/
typedef struct
{
    
    
    VertexType vexs[MAXVEX];   /*vertex*/
    int arc[MAXVEX][MAXVEX];   /*邻接矩阵*/
    int numVertexes, numEdges; /*顶点个数,边个数*/
} MGraph;

Let's look at the structure code of the adjacency list:

//邻接表结构
typedef struct EdgeNode /*边表节点*/
{
    
    
    int adjvex;            /*邻接点域,存储该顶点对应的下标*/
    int weight;            //用于存储权值,非网图可不需要
    struct EdgeNode *next; //链域,指向下一个邻接点
} EdgeNode;

typedef struct VertexNode //定点表结点
{
    
    
    int in;              //顶点入度
    char data;           //顶点域,存储顶点信息
    EdgeNode *firstedge; //边表头指针
} VertexNode, AdjList[MAXVEX];

typedef struct
{
    
    
    AdjList adjList;
    int numVertexes, numEdges; //图中当前顶点数和边数
} graphAdjList, *GraphAdjList;

In order to delete vertices with an in-degree of 0, we also need an auxiliary data structure - the stack .
The following is the code implementation of topological sorting:

//拓扑排序,有环返回0,无环返回1并输出序列
Status TopologicalSort(GraphAdjList GL)
{
    
    
    EdgeNode *e;
    int i, k;
    char gettop;
    int top = 0;   //用于栈指针下标
    int count = 0; //用于统计输出顶点的个数
    char *stack;   //建立栈将入度为0的顶点入栈
    stack = (char *)malloc(GL->numVertexes * sizeof(char));//为栈分配内存空间
    for (i = 0; i < GL->numVertexes; i++)
        if (0 == GL->adjList[i].in)
            stack[++top] = vexs1[i]; //入度为0 的顶点入栈
    int index;
    while (top != 0)
    {
    
    
        gettop = stack[top--];
        for (int kk = 0; kk < MAXVEX; kk++)
            if (vexs1[kk] == gettop)
                index = kk;
        printf("%c -> ", GL->adjList[index].data);
        count++; //输出i顶点,并计数
        for (e = GL->adjList[find_index(gettop)].firstedge; e; e = e->next)
        {
    
    
            k = e->adjvex;
            if (!(--GL->adjList[k].in)) /*将i顶点的邻接点的入度减一,如果减一后等于0,则入栈*/
                stack[++top] = vexs1[k];
        }
    }
    printf("\n");
    if (count < GL->numVertexes)
        return ERROR;
    else
        return OK;
}

Test Data:

// G->arc[0][4] = 1;
    // G->arc[0][5] = 1;
    // G->arc[0][11] = 1;
    // G->arc[1][2] = 1;
    // G->arc[1][4] = 1;
    // G->arc[1][8] = 1;
    // G->arc[2][5] = 1;
    // G->arc[2][6] = 1;
    // G->arc[2][9] = 1;
    // G->arc[3][2] = 1;
    // G->arc[3][13] = 1;
    // G->arc[4][7] = 1;
    // G->arc[5][8] = 1;
    // G->arc[5][12] = 1;
    // G->arc[6][5] = 1;
    // G->arc[8][7] = 1;
    // G->arc[9][10] = 1;
    // G->arc[9][11] = 1;
    // G->arc[10][13] = 1;
    // G->arc[12][9] = 1;

Full code:

#include <stdio.h>
#include <stdlib.h>

#include <math.h>
#include <time.h>

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define MAXEDGE 20
#define MAXVEX 14

typedef int Status; /*Status是函数返回值类型*/
typedef char VertexType;

VertexType vexs1[MAXVEX];
/*邻接矩阵结构*/
typedef struct
{
    
    
    VertexType vexs[MAXVEX];   /*vertex*/
    int arc[MAXVEX][MAXVEX];   /*邻接矩阵*/
    int numVertexes, numEdges; /*顶点个数,边个数*/
} MGraph;

//邻接表结构
typedef struct EdgeNode /*边表节点*/
{
    
    
    int adjvex;            /*邻接点域,存储该顶点对应的下标*/
    int weight;            //用于存储权值,非网图可不需要
    struct EdgeNode *next; //链域,指向下一个邻接点
} EdgeNode;

typedef struct VertexNode //定点表结点
{
    
    
    int in;              //顶点入度
    char data;           //顶点域,存储顶点信息
    EdgeNode *firstedge; //边表头指针
} VertexNode, AdjList[MAXVEX];

typedef struct
{
    
    
    AdjList adjList;
    int numVertexes, numEdges; //图中当前顶点数和边数
} graphAdjList, *GraphAdjList;

// function declaration
void CreateMGraph_matrix(MGraph *G);
void CreateMGraph_list(MGraph *G);
void CreateALGraph(MGraph G, GraphAdjList *GL);
Status TopologicalSort(GraphAdjList GL);
void menu();

void menu()
{
    
    
    printf("Please input the method you want to bulid a graph:\n");
    printf(" 1. Adjacent matrix   2. Adjacent list\n");
    int choice;
    scanf("%d", &choice);
}
void CreateMGraph_matrix(MGraph *G) //邻接矩阵法构建矩阵
{
    
    
    int i, j, k, value;
    G->numEdges = MAXEDGE;
    G->numVertexes = MAXVEX;
    G->arc[MAXVEX][MAXVEX] = {
    
    0};
    G->vexs[MAXVEX] = {
    
    '0'};
    printf("Please input number of vertexs and edges:\n");
    scanf("%d %d", &G->numVertexes, &G->numEdges);
    getchar();
    printf("please input your vertexs\n");
    for (i = 0; i < G->numVertexes; i++)
    {
    
    
        scanf("%c", &G->vexs[i]);
        vexs1[i] = G->vexs[i];
    }
    //初始化
    for (i = 0; i < G->numVertexes; i++)
        for (j = 0; j < G->numVertexes; j++)
            G->arc[i][j] = 0;
    for (k = 0; k < G->numEdges; k++)
    {
    
    
        printf("please input the value of(vi,vj):\n");
        scanf("%d %d %d", &i, &j, &value);
        G->arc[i][j] = value;
    }
    //打印邻接矩阵
    printf("The adjancent matirx is :\n");
    for (i = 0; i < G->numVertexes; i++)
    {
    
    
        for (j = 0; j < G->numVertexes; j++)
            printf("%d ", G->arc[i][j]);
        printf("\n");
    }
    // G->arc[0][4] = 1;
    // G->arc[0][5] = 1;
    // G->arc[0][11] = 1;
    // G->arc[1][2] = 1;
    // G->arc[1][4] = 1;
    // G->arc[1][8] = 1;
    // G->arc[2][5] = 1;
    // G->arc[2][6] = 1;
    // G->arc[2][9] = 1;
    // G->arc[3][2] = 1;
    // G->arc[3][13] = 1;
    // G->arc[4][7] = 1;
    // G->arc[5][8] = 1;
    // G->arc[5][12] = 1;
    // G->arc[6][5] = 1;
    // G->arc[8][7] = 1;
    // G->arc[9][10] = 1;
    // G->arc[9][11] = 1;
    // G->arc[10][13] = 1;
    // G->arc[12][9] = 1;
}

/*邻接矩阵构建邻接表*/
void CreateALGraph(MGraph G, GraphAdjList *GL)
{
    
    
    int i, j;
    EdgeNode *e;

    *GL = (GraphAdjList)malloc(sizeof(graphAdjList));

    (*GL)->numVertexes = G.numVertexes;
    (*GL)->numEdges = G.numEdges;
    for (i = 0; i < G.numVertexes; i++) //读入顶点信息,建立顶点表
    {
    
    
        (*GL)->adjList[i].in = 0;
        (*GL)->adjList[i].data = G.vexs[i];
        (*GL)->adjList[i].firstedge = NULL; //将边表置为空表
    }

    for (i = 0; i < G.numVertexes; i++) //建立边表
    {
    
    
        for (j = 0; j < G.numVertexes; j++)
        {
    
    
            if (G.arc[i][j] == 1)
            {
    
    
                e = (EdgeNode *)malloc(sizeof(EdgeNode));
                e->adjvex = j;                         //邻接序号为j
                e->next = (*GL)->adjList[i].firstedge; //将当前顶点上的指向的节点指针赋值给e
                (*GL)->adjList[i].firstedge = e;       //将当前顶点的指针指向e
                (*GL)->adjList[j].in++;
            }
        }
    }
}
int find_index(char s)
{
    
    
    for (int i = 0; i < MAXVEX; i++)
    {
    
    
        if (vexs1[i] == s)
            return i;
    }
    return 0;
}
//拓扑排序,有环返回0,无环返回1并输出序列
Status TopologicalSort(GraphAdjList GL)
{
    
    
    EdgeNode *e;
    int i, k;
    char gettop;
    int top = 0;   //用于栈指针下标
    int count = 0; //用于统计输出顶点的个数
    char *stack;   //建立栈将入度为0的顶点入栈
    stack = (char *)malloc(GL->numVertexes * sizeof(char));
    for (i = 0; i < GL->numVertexes; i++)
        if (0 == GL->adjList[i].in)
            stack[++top] = vexs1[i]; //入度为0 的顶点入栈
    int index;
    while (top != 0)
    {
    
    
        gettop = stack[top--];
        for (int kk = 0; kk < MAXVEX; kk++)
            if (vexs1[kk] == gettop)
                index = kk;
        printf("%c -> ", GL->adjList[index].data);
        count++; //输出i顶点,并计数
        for (e = GL->adjList[find_index(gettop)].firstedge; e; e = e->next)
        {
    
    
            k = e->adjvex;
            if (!(--GL->adjList[k].in)) /*将i顶点的邻接点的入度减一,如果减一后等于0,则入栈*/
                stack[++top] = vexs1[k];
        }
    }
    printf("\n");
    if (count < GL->numVertexes)
        return ERROR;
    else
        return OK;
}

int main(void)
{
    
    
    MGraph G;
    GraphAdjList GL;
    int result;
    CreateMGraph_matrix(&G);
    CreateALGraph(G, &GL);
    result = TopologicalSort(GL);
    printf("result:%d", result);

    return 0;
}

operation result:
insert image description here

Guess you like

Origin blog.csdn.net/qq_52109814/article/details/121884306