拓扑排序算法C++实现

拓扑排序算法,基本思想:

    1、从有向图中选取一个没有前驱(入度为0)的顶点,并输出之
    2、从有向图中删去此顶点以及所有以它为尾的弧
    3、重复上述两步,直至图空,或者图不空但找不到无前驱的顶点为止

数据结构PPT图论在第七章:http://download.csdn.net/download/include_heqile/10188767

使用邻接表和一个用来存储入度为0的节点的栈实现

在算法中需要用定量的描述替代定性的概念
    没有前驱的顶点   <==> 入度为零的顶点
    删除顶点及以它为尾的弧  <==>  弧头顶点的入度减1

为实现拓扑排序,采用邻接表作为有向图的存储结构,并增设一个入度数组indegree[ ]

为了避免每一次选入度为0的顶点时重复扫描入度数组,可以利用栈来存储入度为0的顶点
代码:有详细注释
#include<stdio.h>
#include<stdlib.h>

#define m 100
#define n 6
#define e 8

typedef struct node1 {
    int info;
    int adjvertex;//这个域就是本节点在数组中的位置
    struct node1 *nextarc;
} glinklistnode;//这个是在后面邻接的节点

typedef struct node2 {
    int vertexinfo;
    glinklistnode *firstarc;
} glinkheadnode;//邻接表的数组,vertexinfo存的是每个点的入度
//数组中的节点比邻接表中的节点多了一个vertexinfo域,用来存储入度值

//创建邻接链表
void createAdjlist(glinkheadnode g[]) {
    int i,j,k;
    glinklistnode *p;
    for(i=0; i<n; i++) {
        g[i].vertexinfo=i;
        g[i].firstarc=0;
    }//初始化每个节点在数组中的位置
    for(k=0; k<e; k++) {
        scanf("%d%d",&i,&j);//输入两个关联节点
        p=(glinklistnode *)malloc(sizeof(glinklistnode));
        p->adjvertex=j;
        p->nextarc=g[i].firstarc;//使用的插入方式建立,后来的更接近根节点
        g[i].firstarc=p;//第一个邻接点是p

    }
}

//拓扑排序函数
void toposort(glinkheadnode g[]) {
    int i,v,w,sum=0, indegree[n];
    struct {
        int s[n];
        int top;
    } stack;//建立一个栈,栈中的s数组用来存入度为0的节点
    glinklistnode *p;
    for (i=0; i<n; i++) indegree[i]=0;//初始化indegree数组,完全可以使用memset
    for (i=0; i<n; i++)
        for(p=g[i].firstarc; p!=0; p=p->nextarc) //这一层for循环用来统计
            indegree[p->adjvertex]++;//经过两个for循环,即可把所有节点的入度算统计出来
    for(i=0,stack.top= -1; i<n; i++) if(indegree[i]==0) {
            stack.top++;
            stack.s[stack.top]=i;
        }//这个for循环用来入栈入度为0的节点
    while(stack.top!= -1) {
        printf("%d\t",stack.s[stack.top]);
        sum=sum+1;
        v=stack.s[stack.top];
        stack.top=stack.top-1;//出栈top
        p=g[v].firstarc;//读取该节点的第一个邻接点
        while (p!=0) {//遍历p的所有邻接点
            w=p->adjvertex;
            indegree[w]=indegree[w]-1;//因为前导节点会被删掉,因此它的入度值需要-1
            if (indegree[w]==0) {//如果它的入度等于0,就将这个节点也入栈
                stack.top=stack.top+1;
                stack.s[stack.top]=w;
            }
            p=p->nextarc;//往下走
        }
    }
    if(sum<n) printf("The AOV network has a cycle\n");//如果最后输出的节点个数少于总结点数,说明图中有回路
}

int main() {
    glinkheadnode g[m];
    createAdjlist(g);
    toposort(g);
    return 0;
}
    原文作者:排序算法
    原文地址: https://blog.csdn.net/include_heqile/article/details/78974437
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞