zoukankan      html  css  js  c++  java
  • 拓扑排序(有向无环图)

      拓扑排序含义:对一个有向无环图G进行拓扑排序,将G中所有顶点构成一个线性序列,对于图中任一顶点v1和v2,如果有弧<v1,v2>属于图G的,则在序列中v1要排在v2前.面,如果该有向无环图满足上述条件,这样的线性表序列就是拓扑排序序列

    1.创建结构体

    //定义表结点
    typedef struct ENode{
        int index;//连接顶点的下标
        struct ENode *next; 
    }ENode; 
    
    //表顶点
    typedef struct Node{
        int in;  //入度 
        char data;  //顶点数据
        struct ENode *firstNode;  //指向表结点的指针 
    }Node; 
    
    //邻接链表 
    typedef struct Graph{
        int vexNum;
        int arcNum;
        Node vexs[MAX]; 
    }Graph,*myGraph;

    2.创建有向无环图

    void createGraph(myGraph &G)
    {
        G=(Graph*)malloc(sizeof(Graph)); //动态申请空间
        
        int i,j,k;
        char v1,v2;    //边的两个顶点 
        printf("请输入顶点的数量:");
        scanf("%d",&G->vexNum);
        printf("请输入边的数量:");
        scanf("%d",&G->arcNum);
        
        printf("请依次将顶点数据输入进来
    ");
        for(i=0;i<G->vexNum;i++)   //初始化顶点 
        {
            getchar();
            scanf("%c",&G->vexs[i].data);
            G->vexs[i].firstNode=NULL;  //初始化为空 
            G->vexs[i].in=0;  //初始化入度为0 
        }
        
        printf("请依次将边输入进来
    ");
        for(i=0;i<G->arcNum;i++)
        {
            getchar();
            scanf("%c%c",&v1,&v2);
            
            j=getLocate(G,v1);  //获取下标
            k=getLocate(G,v2);  //获取下标
            
            ENode *currentNode=(ENode*)malloc(sizeof(ENode));
            currentNode->index=k;   //顶点下标 
            currentNode->next=NULL;
            G->vexs[k].in++;    //k的下标入度加1
        
            if(G->vexs[j].firstNode==NULL)//当该顶点没有邻接点时  
            {
                G->vexs[j].firstNode=currentNode; //指向这个结点 
            } 
            else  //当该顶点有邻接点时   直接在链的头部进行插入  不是在尾部插入 
            {
                
                ENode *node=G->vexs[j].firstNode; //储存第一个结点 
                G->vexs[j].firstNode=currentNode; //新节点变成第一个结点 
                currentNode->next=node;   //新的第一个结点指向旧的第一个结点 
            }
        }  
    }

    3.拓扑排序

    void  TopologicalSort(myGraph G)  //满足栈后进先出的个性 
    {
        int top=0;  //栈指针
        int count=0;  //打印次数
        ENode *node; //避免 G->vexs[i].firstNode发生改变
        int *stack; //栈数组
        int getTop; //获取栈顶顶点下标 
        int i,j;
        
        stack=(int*)malloc(G->vexNum*sizeof(int)); //动态生成一个数组
        if(!stack)
        {
            printf("动态生成失败
    ");
        }
        
        for(int i=0;i<G->vexNum;i++)  //先将度为0的先入栈 
        {
            if(G->vexs[i].in==0)
            {
                stack[++top]=i;  //储存入栈顶点的下标 ,从top=1开始 
            }
        } 
        
        while(top!=0)  //当top等于0时,没有出栈元素了 
        {
            int getTop=stack[top--];  //出栈操作 
            printf("%c ",G->vexs[getTop].data);  
            count++;  //用来判断有没有环 
            
            for(node=G->vexs[getTop].firstNode;node!=NULL;node=node->next) 
            {
                j=node->index;  //获取顶点的下标
                if(!(--G->vexs[j].in)) //如果入度为0则入栈 
                {
                    stack[++top]=j;
                }
            }
        }
        
        if(count<G->vexNum) 
        {
            printf("该图有环
    ");
        }
    }

    所有的代码如下:

    #include<stdio.h>
    #include<stdlib.h>
    
    #define MAX 20
    
    //定义表结点
    typedef struct ENode{
        int index;//连接顶点的下标
        struct ENode *next; 
    }ENode; 
    
    //表顶点
    typedef struct Node{
        int in;  //入度 
        char data;  //顶点数据
        struct ENode *firstNode;  //指向表结点的指针 
    }Node; 
    
    //邻接链表 
    typedef struct Graph{
        int vexNum;
        int arcNum;
        Node vexs[MAX]; 
    }Graph,*myGraph;
    
    //获取顶点的下标
    int getLocate(myGraph G,char v)
    {
        int i;
        for(i=0;i<G->vexNum;i++)
        {
            if(v==G->vexs[i].data)
            {
                return i;
            }
        }
        return -1;
    }
    
    //有向的邻接链表的创建
    void createGraph(myGraph &G)
    {
        G=(Graph*)malloc(sizeof(Graph)); //动态申请空间
        
        int i,j,k;
        char v1,v2;    //边的两个顶点 
        printf("请输入顶点的数量:");
        scanf("%d",&G->vexNum);
        printf("请输入边的数量:");
        scanf("%d",&G->arcNum);
        
        printf("请依次将顶点数据输入进来
    ");
        for(i=0;i<G->vexNum;i++)   //初始化顶点 
        {
            getchar();
            scanf("%c",&G->vexs[i].data);
            G->vexs[i].firstNode=NULL;  //初始化为空 
            G->vexs[i].in=0;  //初始化入度为0 
        }
        
        printf("请依次将边输入进来
    ");
        for(i=0;i<G->arcNum;i++)
        {
            getchar();
            scanf("%c%c",&v1,&v2);
            
            j=getLocate(G,v1);  //获取下标
            k=getLocate(G,v2);  //获取下标
            
            ENode *currentNode=(ENode*)malloc(sizeof(ENode));
            currentNode->index=k;   //顶点下标 
            currentNode->next=NULL;
            G->vexs[k].in++;    //k的下标入度加1
        
            if(G->vexs[j].firstNode==NULL)//当该顶点没有邻接点时  
            {
                G->vexs[j].firstNode=currentNode; //指向这个结点 
            } 
            else  //当该顶点有邻接点时   直接在链的头部进行插入  不是在尾部插入 
            {
                
                ENode *node=G->vexs[j].firstNode; //储存第一个结点 
                G->vexs[j].firstNode=currentNode; //新节点变成第一个结点 
                currentNode->next=node;   //新的第一个结点指向旧的第一个结点 
            }
        }  
    }
    
    //打印该邻接表
    void printfGraph(Graph G)  //打印表不要用指针,这样可能会改变图的结构 
    {
        for(int i=0;i<G.vexNum;i++)
        {
            printf("%d ",G.vexs[i].in);
            printf("%c ",G.vexs[i].data);
            while(G.vexs[i].firstNode!=NULL)
            {
                printf("%d ",G.vexs[i].firstNode->index);
                G.vexs[i].firstNode=G.vexs[i].firstNode->next;
            }
            printf("
    ");
        } 
    }
    
    //拓扑排序
    void  TopologicalSort(myGraph G)  //满足栈后进先出的个性 
    {
        int top=0;  //栈指针
        int count=0;  //打印次数
        ENode *node; //避免 G->vexs[i].firstNode发生改变
        int *stack; //栈数组
        int getTop; //获取栈顶顶点下标 
        int i,j;
        
        stack=(int*)malloc(G->vexNum*sizeof(int)); //动态生成一个数组
        if(!stack)
        {
            printf("动态生成失败
    ");
        }
        
        for(int i=0;i<G->vexNum;i++)  //先将度为0的先入栈 
        {
            if(G->vexs[i].in==0)
            {
                stack[++top]=i;  //储存入栈顶点的下标 ,从top=1开始 
            }
        } 
        
        while(top!=0)  //当top等于0时,没有出栈元素了 
        {
            int getTop=stack[top--];  //出栈操作 
            printf("%c ",G->vexs[getTop].data);  
            count++;  //用来判断有没有环 
            
            for(node=G->vexs[getTop].firstNode;node!=NULL;node=node->next) 
            {
                j=node->index;  //获取顶点的下标
                if(!(--G->vexs[j].in)) //如果入度为0则入栈 
                {
                    stack[++top]=j;
                }
            }
        }
        
        if(count<G->vexNum) 
        {
            printf("该图有环
    ");
        }
    }
    
    int main()
    {
        Graph *G;  //申明邻接链表的对象
        createGraph(G);  //创建邻接链表
        printfGraph(*G);   //打印该邻接链表 
        
        printf("该有向图的拓扑排序如下:");
        TopologicalSort(G);    
    }

      

  • 相关阅读:
    Ubuntu配置sublime text 3的c编译环境
    ORA-01078错误举例:SID的大写和小写错误
    linux下多进程的文件拷贝与进程相关的一些基础知识
    ASM(四) 利用Method 组件动态注入方法逻辑
    基于Redis的三种分布式爬虫策略
    Go语言并发编程总结
    POJ2406 Power Strings 【KMP】
    nyoj 会场安排问题
    Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds. If the server requires more time, try increasing the timeout in the server editor.
    Java的String、StringBuffer和StringBuilder的区别
  • 原文地址:https://www.cnblogs.com/qian-yi/p/12787383.html
Copyright © 2011-2022 走看看