图论算法——思路超清晰的拓扑排序

最近在学习数据结构与算法分析——C语言描述这本书,话说都买了1年多了都没有看,最近有时间了就捡起来吧。直接上代码:

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

#define MAX_VERTEX_NUM 7

int TopNum[7];

typedef struct EdgeNode    // 邻接顶点
{
    int adjvertex;
    struct EdgeNode *next;
}EdgeNode;

typedef struct VertexNode    // 顶点
{
    int vertex;
    EdgeNode *firstEdge;
}VertexNode, HeadCellArray[MAX_VERTEX_NUM];

typedef struct         // 图结构
{
    int numVertex, numEdge;
    HeadCellArray headCellArray;
}Graph;


int * MakeIndegree(Graph G)
{
    int i;
    int *indegree;
    EdgeNode *p;

    indegree=(int*)malloc(sizeof(int)*G.numVertex);

    for (i=0;i<G.numVertex;i++)
    {
        p = G.headCellArray[i].firstEdge;
        while(p)
        {
            (indegree[p->adjvertex])++;
            p = p->next;
        }
    }

    return indegree;
}

int FindNewVertexOfIndegreeZero(int *indegree, int n)
{
    int i, temp, NotAVertex=-1, IndegreeZero;
    for (i=0;i<n;i++)
    {
        if (indegree[i] == 0)
        {
            indegree[i] = 100;             // 100表示该顶点已被分配
            IndegreeZero = i;
            break;
        }
    }

    if (IndegreeZero != -1)
        return IndegreeZero;
    return NotAVertex;
}

void Topsort(Graph G)
{
    int counter;
    int v, w;
    int *indegree;
    EdgeNode *p;
    indegree = MakeIndegree(G);

    for (counter=0;counter<G.numVertex;counter++)
    {
        v = FindNewVertexOfIndegreeZero(indegree, G.numVertex);
        if (v == -1)
        {
            printf("%s", "Graph has cycle.");
            break;
            return;
        }

        TopNum[v] = counter;
        p = G.headCellArray[v].firstEdge;
        while(p)
        {
            w=p->adjvertex;
            indegree[w]--;
            p = p->next;
        }
    }
    
    return;
}

Graph InitGraph()
{
    Graph G;
    EdgeNode *p;
    int i, u, v;

    printf("请输入节点数和边数:
");
    scanf("%d%d", &G.numVertex, &G.numEdge);

    for (i=0;i<G.numVertex;i++)
    {
        G.headCellArray[i] = *(VertexNode*)malloc(sizeof(VertexNode));
        G.headCellArray[i].vertex=i;
        G.headCellArray[i].firstEdge=NULL;
    }

    for (i=0;i<G.numEdge;i++) 
    {
        printf("请输入边(u, v),即u->v
");
        scanf("%d%d", &u, &v);

        p=(EdgeNode*)malloc(sizeof(EdgeNode));
        p->adjvertex=v;
        p->next=G.headCellArray[u].firstEdge;
        G.headCellArray[u].firstEdge=p;
    }

    return G;
}

void PrintGraph(Graph G)
{
    int i;
    EdgeNode *p;

    for(i=0;i<G.numVertex;i++)
    {
        printf("顶点%d", G.headCellArray[i].vertex);
        p=G.headCellArray[i].firstEdge;
        while(p)
        {
            printf("->%3d", p->adjvertex);
            p=p->next;
        }
        printf("
");
    }
}

void main()
{
    int i, *p, temp;
    Graph G;

    G=InitGraph();
    PrintGraph(G);

/*
    p=MakeIndegree(G);
    for(i=0;i<7;i++)
        printf("%4d", p[i]);
*/
/*
    temp=FindNewVertexOfIndegreeZero(p, 7);
    printf("%d
", temp);
*/
    Topsort(G);    
    for(i=0;i<MAX_VERTEX_NUM;i++)
        printf("%4d
", TopNum[i]);

}

这里只对我编程时遇到的几个问题进行简单的说明:

1.malloc函数的使用,很久没有用C了,所以开始的时候是这样用的:

G.headCellArray[i] = (VertexNode)malloc(sizeof(VertexNode));

     产生的错误困扰了我半天。

2.另一个错误是在编写函数的时候没有注意到前向引用的问题,MakeIndegree(Graph G);等函数放在了Topsort(Graph G);后面导致错误。

3.最后一个问题是FindNewVertexOfIndegreeZero(int *indegree, int n);中忘记break了,导致输出序列错误。

注:TopNum输出的序列不是最后的拓扑序列,它是key,和value反的,value代表的是下面下标应该在的位置。

原文地址:https://www.cnblogs.com/selfimprovement/p/5991290.html