• 拓扑排序(有向无环图)


      拓扑排序含义:对一个有向无环图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);    
    }

      

  • 相关阅读:
    iOS 字符串的UTF8 编码 以及归档反归档
    iOS 关于关键字高亮
    iOS 适配 ,关于prefix Header 文件的配置
    关于collectionView 的头视图
    关于页面的下拉刷新,和上拉加载 --- > collectionView ,tableView
    Nums数独计算器的感谢版,有3种解题方式,过去注册的也是可以用
    Nums数独计算器,良心软件,给不给钱都是可以的
    人生不过是给自己找一些痕迹,证明自己存在过
    做些有益的事情,人生要懂得自重
    振作才是自己可以走的路,人生不要放弃自己的争取
  • 原文地址:https://www.cnblogs.com/qian-yi/p/12787383.html
Copyright © 2020-2023  润新知