拓朴排序

 
#include < iostream .h >
//图的邻接表不是唯一的,因为在每个顶点的邻接表中,各边结点的链接次序可以任意安排,
//其具体链接次序与边的输入次序和生成算法有关。

//下面给出建立图的邻接表的有关类型定义和生成一个有向图邻接表的算法描述
typedef int VertexType;//这里有分号 #define才没有分号
const int MaxVertexNum=20;//{图的最大顶点数,它应不小于具体图的顶点数n};
const int MaxEdgeNum=30;//{图的最大边数,它应不小于具体图的最大边数e};
typedef VertexType vexlist[MaxVertexNum];//定义vexlist为存储顶点信息的数组类型
struct edgenode//定义邻接表中的边结点类型
{
    int adjvex;//邻接点域
    int weight;//权值域,对无权图可省去
    edgenode *next;//指向下一个边结点的链域
};//边忘了这个分号
typedef edgenode *adjlist[MaxVertexNum];//这义adjlist为存储n个表头指针的数组类型

void Create2(vexlist GV,adjlist GL,int n,int e)    //看看GL到底是什么: GL[i]->adjvex
         //通过从键盘上输入的n个顶点信息和e条有向边的信息
         //建立顶点数组GV和邻接表GL
{
    int i,j,k,w;
    //建立顶点数组
    cout
< <"输入"<<n <<"个顶点"<<endl;
    for(i
=0;i<n;i++)
        
cin > >GV[i];
    //初始化邻接表,即将表头向量中的每个域置空
    for(i=0;i
< n ;i++)
        GL[i]
=NULL;
    
//建立邻接表
    cout<<"输入"<<e<<"条边"<<endl;
    for(k
=1;k<=e;k++)
    
{
        //输入一条边<i,j
>
        cin>>i>>j;//>>w;
        //由系统分配一个新结点
        edgenode *p=new edgenode;
        //将j的值赋给新结点的邻接点域
        p->adjvex=j;
        //p->weight=w;
        //将新结点插入到vi邻接表的表头
        p->next=GL[i];
        GL[i]=p;
    }
}
void Toposort(adjlist GL,int n)//此算法的时间复杂度为o(n+e) //n为顶点数,e为边数
       //利用邻接表GL表示的有向图进行拓朴排序
{
    
    int i,j,k,top,m=0;//m用来统计拓朴序列中的顶点
    //top的值为一个入度为0的顶点序号,top指向的值为下一个入度为0的顶点序号
    edgenode *p;
    //定义存储图中每个顶点入度的一维整型数组d
    int *d=new int[n];
    //初始化数组d中的每个元素值为0
    for(i=0;i
< n ;i++)
        d[i]
=0;
    
//利用数组d中的对应元素统计出每个顶点的入度
    for(i
=0;i<n;i++)
    
{
        p
=GL[i];
        
while(p! =NULL)
        
{
            j
=p- > adjvex;
            d[j]++;
            p=p->next;
        }
    }
    //初始化用于链接入度为0的元素的栈的栈顶指针top为-1
    top=-1;
    //建立初始化栈
    for(i=0;i
< n ;i++)
        if(d[i]
==0)
        
{
            d[i]
=top;
            
top =i;
        
}
        //每循环一次删除一个顶点及所有出边
        cout<<"拓朴序列如下:"<<endl;
    while(top!
=-1)
    
{
        j
=top;//j的值为一个入度为0的顶点序号
        
top =d[top];//删除栈顶点元素
        
cout<<j<<" ";//输出一个顶点
        m++;//输出的顶点个数加1
        p
=GL[j];//p指向vj邻接点表的第一个结点
        
while(p! =NULL)
        
{
            k
=p- > adjvex;//vk是vj的一个邻接点
            d[k]--;//vk的入度减1
            if(d[k]==0)//把入度为0的元素进栈
            {
                d[k]=top;
                top=k;

            }
            p=p->next;//p指向vj邻接点表的下一个结点
        }

    }
    cout
< <endl ;
    if(m<n)//当输出的顶点数小于图中的顶点数时,输出有回路信息(拓朴图是无回路的,因
        //为若带有回路,则回路上的所有活动都无法进行)
    {
        cout<<"The network has a cycle!"<<endl;
    }
}

void main()
{
    vexlist GV;
    adjlist GL;

    int n
=6;
    
int e =8;
    
Create2(GV,GL,n,e);
    //cout<<GL[0]-
> adjvex;
    Toposort(GL,n);
}
//测试用例如下:
/*
输入6个顶点
0 1 2 3 4 5
输入8条边
0 2
1 2
1 3
1 4
2 3
3 5
4 5
2 5
拓朴序列如下:
1 4 0 2 3 5
*/

/*
http://java2.xinwen365.net

QQ群:
34409541 讨论网页  
34409326 讨论JAVA 已满 
34408784 讨论VC++  
34409699 讨论VC++  
9143041 讨论MFC编程  
10614204 讨论C#  
10613030 讨论Win32编程  
10613067 讨论游戏开发  
18779860 讨论JAVA  
*/
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
排序是一种用于有向无环图(DAG)的排序算法。在DAG中,每个节点代表一个任务,边表示任务间的依赖关系,即若任务A依赖于任务B,则边从B指向A。排序将DAG中的所有任务排成一个线性序列,使得对于任意一对有依赖关系的任务,其排列顺序都符合依赖关系。 以下是用数组表示法实现排序的C语言代码: ```c #include <stdio.h> #define MAXN 100 // 最大节点数 int n; // 节点数 int G[MAXN][MAXN]; // 邻接矩阵表示有向图 int inDegree[MAXN]; // 记录每个节点的入度 int queue[MAXN]; // 用于排序的队列 int front, rear; // 队列的头尾指针 void topoSort() { int i, j, k; // 初始化队列 front = rear = 0; for (i = 0; i < n; i++) { if (inDegree[i] == 0) { queue[rear++] = i; } } // 排序 while (front < rear) { int u = queue[front++]; // 取出队首节点 printf("%d ", u); // 输出节点编号 for (j = 0; j < n; j++) { if (G[u][j]) { // 若u->j有一条边 if (--inDegree[j] == 0) { // j的入度减1 queue[rear++] = j; // 若j的入度为0,则入队 } } } } printf("\n"); } int main() { int i, j, u, v; scanf("%d", &n); for (i = 0; i < n; i++) { for (j = 0; j < n; j++) { G[i][j] = 0; // 初始化邻接矩阵 } inDegree[i] = 0; // 初始化入度数组 } // 读入有向边,构建邻接矩阵 while (scanf("%d%d", &u, &v) != EOF) { G[u][v] = 1; inDegree[v]++; } // 排序 topoSort(); return 0; } ``` 该代码通过邻接矩阵表示有向图,使用一个数组记录每个节点的入度,使用一个队列进行排序。在每次排序中,将入度为0的节点加入队列中,然后依次取出队首节点,输出其编号,并将与它相邻的节点的入度减1,若减1后入度为0,则将该节点入队。直到队列为空为止。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值