ACM模板——拓扑排序算法

注释版(邻接表_版本):

#include<bits/stdc++.h>

#define mem(a,b) memset(a,b,sizeof a);

using namespace std;

typedef long long ll;

const int MAXV=1000;

// 边结点
struct ENode
{
    int adjvex; // 邻接点:弧头顶点(下标)
    int weight; // 权值
    ENode *next; // 链域,下一个邻接点
};

// 顶点结点
typedef struct VNode
{
    int in;        // 入度
    int data;      // 顶点信息
    ENode *firstE; // 边表头指针
}AdjList[MAXV];

// 邻接表
typedef struct gAList
{
    AdjList adjList;
    int numV,numE; // 顶点数  边数
}*GAList;

int TopoSort(GAList GAL) // 拓扑排序
{
    ENode *e;
    int top=0; // 用于sk栈指针下标
    int cnt=0; // 统计输出顶点的个数
    int *sk; // 建栈,存储入度为0的顶点
    sk=(int *)malloc(GAL->numV*sizeof(int));

    for(int i=0;i<GAL->numV;i++)
        if(GAL->adjList[i].in==0)
            sk[++top]=i; // 将入度为0的顶点入栈;++top 从1开始,为下文 while(top!=0) 做准备

    while(top!=0)
    {
        int gettop=sk[top--]; // 出栈
        printf("%d -> ",GAL->adjList[gettop].data);
        cnt++; // 统计输出顶点数
        for(e=GAL->adjList[gettop].firstE; e; e=e->next) // 对此顶点弧表遍历
        {
            int k=e->adjvex;
            if(!(--GAL->adjList[k].in)) // 将k号顶点邻接点的入度-1
                sk[++top]=k; // 若为0则入栈,方便下次循环输出
        }
    }

    if(cnt<GAL->numV) // 若 cnt 小于顶点数,则存在环
        return 0;
    else
        return 1;
}


简化版(邻接表_版本):

#include<bits/stdc++.h>

#define mem(a,b) memset(a,b,sizeof a);

using namespace std;

typedef long long ll;

const int MAXV=1000;

struct ENode
{
    int adjvex; 
    int weight; 
    ENode *next; 
};

typedef struct VNode
{
    int in;        
    int data;      
    ENode *firstE; 
}AdjList[MAXV];

typedef struct gAList
{
    AdjList adjList;
    int numV,numE;
}*GAList;

int TopoSort(GAList GAL)
{
    ENode *e;
    int top=0; 
    int cnt=0; 
    int *sk; 
    sk=(int *)malloc(GAL->numV*sizeof(int));

    for(int i=0;i<GAL->numV;i++)
        if(GAL->adjList[i].in==0)
            sk[++top]=i; 

    while(top!=0)
    {
        int gettop=sk[top--]; 
        printf("%d -> ",GAL->adjList[gettop].data);
        cnt++; 
        for(e=GAL->adjList[gettop].firstE; e; e=e->next) 
        {
            int k=e->adjvex;
            if(!(--GAL->adjList[k].in)) 
                sk[++top]=k; 
        }
    }

    if(cnt<GAL->numV) 
        return 0;
    else
        return 1;
}



注释版(邻接矩阵_版本):

#include<bits/stdc++.h>
#include<cmath>

#define mem(a,b) memset(a,b,sizeof a)

using namespace std;

typedef long long ll;

const int MAXV=1010;

// 邻接矩阵
int mp[MAXV][MAXV]; // 边结点
int in[MAXV]; // 入度
int n,m;

void TopoSort()
{
    int top=-1; // 回路标记
    for(int i=0;i<n;i++)
    {
        if(in[i]==0)
        {
            in[i]=top; // 类似next[]存储
            top=i; // FILO思想
        }
    }

    for(int i=0;i<n;i++)
    {
        if(top==-1) // 存在回路
        {
            return ;
        }
        else
        {
            int j=top;
            top=in[top]; // 每次都是 -1,做标记,看接下来for_k是否有符合的新零度点。若没有,存在回路
            printf("%d ",j); // 输出结果
            for(int k=0;k<n;k++)
            {
                if(mp[j][k] && --in[k]==0) // 将j号顶点邻接点k的入度-1
                {
                    in[k]=top; // 同上
                    top=k; // 同上
                }
            }
        }
    }
}


简化版(邻接矩阵_版本):

#include<bits/stdc++.h>
#include<cmath>

#define mem(a,b) memset(a,b,sizeof a)

using namespace std;

typedef long long ll;

const int MAXV=1010;

int mp[MAXV][MAXV];
int in[MAXV];
int n,m;

void TopoSort()
{
    int top=-1;
    for(int i=0;i<n;i++)
    {
        if(in[i]==0)
        {
            in[i]=top;
            top=i;
        }
    }

    for(int i=0;i<n;i++)
    {
        if(top==-1)
        {
            return ;
        }
        else
        {
            int j=top;
            top=in[top];
            printf("%d ",j);
            for(int k=0;k<n;k++)
            {
                if(mp[j][k] && --in[k]==0)
                {
                    in[k]=top;
                    top=k;
                }
            }
        }
    }
}

猜你喜欢

转载自blog.csdn.net/dream_weave/article/details/79998742