zoukankan      html  css  js  c++  java
  • 拓扑排序之变量序列代码

    /*
    Name: 
    Copyright: 
    Author: 
    Date: 17-11-14 21:02
    Description: 拓扑排序之变量序列 
    如果有n个变量(1<=n<=26,变量名用单个小写字母表示)。还有m个二元组(u,v),分别表示变量u小于v。

    那么,全部变量从小到大排列起来应该是什么样子的呢?
    比如有4个变量a,b,c,d,若以知a<b,c<b,d<c,则这4个变量的排序可能是a<d<c<b。

    虽然还有可能其它的可能,你仅仅需找出当中的一个就可以。
    Input
    输入为一个字符串data,当中包括N+N个字符。表示N个关系式(1<=N<=100000),比如序列"abcbdc"表示a<b,c<b,d<c.
    Output
    给出一个字符串,当中存储了一个符合要求的变量序列,比如,字符串"adcb"表示a<d<c<b。 

    */
    #include<stdio.h>
    #include<stdlib.h>


    #define true 1  
    #define false 0
    #define MAXM 26   //最大变量(顶点)数量 
    #define MAXN 100000   //最大关系式数量 


    typedef char VertexType; //顶点类型由用户自己定义
    typedef int EdgeType; //边上的权值类型由用户自己定义


    typedef struct EdgeNode{ //边表结点
    int adjvex;  //邻接点域,存储该顶点相应的下标
    // EdgeType weight; //权值。对于非网图能够不须要 
    struct EdgeNode *next; //链域,指向下一个邻接点 
    } EdgeNode;


    typedef struct VertexNode{ //顶点表结点
    VertexType data; //顶点域,存储顶点信息
    int in;   //存储顶点入度的数量 
    EdgeNode *firstEdge; //边表头指针
    } VertexNode;


    typedef struct Edge{ //边集数组 
    int u, v; //弧尾和弧头 
    int next; //指向同一个弧尾的下一条边 
    // EdgeType weight; //权值,对于非网图能够不须要 
    } EdgeLib;


    int book[MAXM] = {0}; //标记某字母是否出现 


    int IsTopoSeq(char *data, char *topo);//依据关系列表data,推断topo字符串是否为拓扑序列 
    int CreateGraph(char *data, VertexNode *GL);//创建一个图
    void PrintGraph(VertexNode *GL);//输出图
    int TopoLogicalSort_DFS(char *topo, VertexNode *GL, int n);//拓扑排序,获取拓扑序列,若存在环则返回假 
    int TopoLogicalSort_BFS(char *topo, VertexNode *GL, int n);//拓扑排序,获取拓扑序列。若存在环则返回假 
    int CreateGraph_2(char *data, int In[], int first[], EdgeLib edge[]);//创建一个图
    void PrintGraph_2(int first[], EdgeLib edge[]);//输出图
    int TopoLogicalSort(char *topo, EdgeLib edge[], int In[], int first[], int n);//拓扑排序。获取拓扑序列,若存在环则返回假,使用队列存储拓扑序列 


    int main()
    {
    int i, n;
    VertexNode GL[MAXM];
    char topo[MAXM+1];
    char data[MAXN+MAXN+1];
    int In[MAXM], first[MAXM]; //存储顶点信息
    EdgeLib edge[MAXN]; //存储边信息 


    gets(data); 
    n = CreateGraph_2(data, In, first, edge);//创建一个图
    PrintGraph_2(first, edge);//输出图

    if (TopoLogicalSort(topo, edge, In, first, n))//採用拓扑排序构造拓扑序列 
    puts(topo);
    else
    puts("不存在满足条件的序列"); 

    if (IsTopoSeq(data, topo))//依据关系列表data。推断topo字符串是否为拓扑序列 
    puts(topo);
    else
    puts("不存在满足条件的序列");

    gets(data); 
    n = CreateGraph(data, GL);//创建一个图
    PrintGraph(GL);//输出图
    if (IsTopoSeq(data, topo))//依据关系列表data,推断topo字符串是否为拓扑序列 
    puts(topo);
    else
    puts("不存在满足条件的序列");

    if (TopoLogicalSort_BFS(topo, GL, n))//採用拓扑排序构造拓扑序列 
    puts(topo);
    else
    puts("不存在满足条件的序列"); 

    gets(data); 
    n = CreateGraph(data, GL);//创建一个图
    PrintGraph(GL);//输出图

    if (TopoLogicalSort_DFS(topo, GL, n))//採用拓扑排序构造拓扑序列 
    puts(topo);
    else
    puts("不存在满足条件的序列"); 

    if (IsTopoSeq(data, topo))//依据关系列表data,推断topo字符串是否为拓扑序列 
    puts(topo);
    else
    puts("不存在满足条件的序列");




        return 0;
    }
    /*
    函数名称:CreateGraph
    函数功能:把顶点和边信息读入到表示图的邻接表中 
    输入变量:char *data:存储了N个关系式的字符串 
              VertexNode *GL : 顶点表数组 
    输出变量:表示图的顶点表数组 
    返回值:int :顶点数量 
    */ 
    int CreateGraph(char *data, VertexNode *GL)
    {
    int i, u, v;
    int count = 0;//记录顶点数量 
    EdgeNode *e;

    for (i=0; i<MAXM; i++)//初始化图 
    {
    GL[i].data = i + 'a';
    GL[i].in = 0;
    GL[i].firstEdge = NULL;
    book[i] = 0;
    }

    for (i=0; data[i]!=''; i+=2)//每次读取两个变量  
    {
    u = data[i] - 'a'; //字母转换为数字,'a'相应0,'b'相应1。以此类推 
    v = data[i+1] - 'a';
    book[u] = book[v] = 1;

    e = (EdgeNode*)malloc(sizeof(EdgeNode)); //採用头插法插入边表结点 
    if (!e)
    {
    puts("Error"); 
    exit(1);
    }
    e->adjvex = v;
    e->next = GL[u].firstEdge;
    GL[u].firstEdge = e;

    GL[v].in++;
    }

    for (i=0; i<MAXM; i++)//计算顶点数量 
    {
    if (book[i] != 0)
    count++;
    }

    return count;



    void PrintGraph(VertexNode *GL)//输出图
    {
    int u, v;
    EdgeNode *e;

    for (u=0; u<MAXM; u++)
    {
    printf("G[%d] = %c: ", u, GL[u].data);
    for (e=GL[u].firstEdge; e!=NULL; e=e->next)//将u的邻接点入度减1。并将入度为0的顶点入栈 
    {
    v = e->adjvex;
    printf("<%c, %c>, ", GL[u].data, GL[v].data);
    }
    printf(" ");
    }
    printf(" ");



    /*
    函数名称:TopoLogicalSort_DFS
    函数功能:拓扑排序,採用深度优先搜索获取拓扑序列
    输入变量:char *topo:用来存储拓扑序列的字符串 
              VertexNode *GL : 顶点表数组 
              int n:顶点个数 
    输出变量:用来存储拓扑序列的字符串
    返回值:int :拓扑排序成功返回真,若存在环则返回假
    */ 
    int TopoLogicalSort_DFS(char *topo, VertexNode *GL, int n)
    {
    int i, u, v, top;
    int count = 0; //用于统计输出顶点的个数 
    EdgeNode *e;
    int Stack[MAXM];

    for (top=i=0; i<MAXM; i++)//将入度为0的顶点入栈 
    {
    if (book[i] != 0 && GL[i].in == 0)
    {
    Stack[top++] = i;
    }
    }

    while (top > 0)//採用深度优先搜索获取拓扑序列 
    {
    u = Stack[--top];
    topo[count++] = u + 'a';

    for (e=GL[u].firstEdge; e!=NULL; e=e->next)//将u的邻接点入度减1,并将入度为0的顶点入栈 
    {
    v = e->adjvex;
    if (--GL[v].in == 0)
    Stack[top++] = v;
    }
    }
    topo[count] = '';

    return (count == n);//假设count小于顶点数,说明存在环 
    }


    /*
    函数名称:TopoLogicalSort_BFS
    函数功能:拓扑排序,採用广度优先搜索获取拓扑序列
    输入变量:char *topo:用来存储拓扑序列的字符串 
              VertexNode *GL : 顶点表数组 
              int n:顶点个数 
    输出变量:用来存储拓扑序列的字符串
    返回值:int :拓扑排序成功返回真。若存在环则返回假
    */ 
    int TopoLogicalSort_BFS(char *topo, VertexNode *GL, int n)
    {
    int i, u, v, front, rear;
    EdgeNode *e;

    front = rear = 0;
    for (i=0; i<MAXM; i++)//将入度为0的顶点入栈 
    {
    if (book[i] != 0 && GL[i].in == 0)
    {
    topo[rear++] = i + 'a';
    }
    }

    while (front < rear)//採用广度优先搜索获取拓扑序列 
    {
    u = topo[front++] - 'a';

    for (e=GL[u].firstEdge; e!=NULL; e=e->next)//将u的邻接点入度减1。并将入度为0的顶点入栈 
    {
    v = e->adjvex;
    if (--GL[v].in == 0)
    topo[rear++] = v + 'a';
    }
    }
    topo[rear] = '';

    return (rear == n);//假设count小于顶点数,说明存在环 
    }


    /*
    函数名称:CreateGraph_2
    函数功能:把顶点和边信息读入到表示图的边表集中 
    输入变量:char *data:存储了N个关系式的字符串 
              int In[]:存储了顶点的入度信息 
              int first[]:指向以该顶点为弧尾的第一条边 
              EdgeLib edge[]:存储了边信息的边表集 
    输出变量:表示图的边表集数组 
    返回值:int :顶点数量 
    */ 
    int CreateGraph_2(char *data, int In[], int first[], EdgeLib edge[])//创建一个图
    {
    int i, j;
    int count = 0;//记录顶点数量 

    for (i=0; i<MAXM; i++)//初始化图 
    {
    first[i] = -1;
    book[i] = 0;
    In[i] = 0;
    }

    for (j=i=0; data[i]!=''; i+=2,j++)//每次读取两个变量  
    {
    edge[j].u = data[i] - 'a'; //字母转换为数字,'a'相应0,'b'相应1,以此类推 
    edge[j].v = data[i+1] - 'a';
    book[edge[j].u] = book[edge[j].v] = 1;

    edge[j].next = first[edge[j].u];
    first[edge[j].u] = j;
    In[edge[j].v]++;
    }

    for (i=0; i<MAXM; i++)//计算顶点数量 
    {
    if (book[i] != 0)
    count++;
    }

    return count;



    void PrintGraph_2(int first[], EdgeLib edge[])//输出图
    {
    int i, j;

    for (i=0; i<MAXM; i++)
    {
    printf("G[%d] = %c: ", i, i+'a');
    j = first[i]; //指向i的第一条边 
    while (j != -1)
    {
    printf("<%c, %c>, ", edge[j].u+'a', edge[j].v+'a');
    j = edge[j].next; //指向下一条边 
    }
    printf(" ");
    }
    printf(" ");

    /*
    函数名称:TopoLogicalSort
    函数功能:拓扑排序。採用广度优先搜索获取拓扑序列
    输入变量:char *topo:用来存储拓扑序列的字符串 
              EdgeLib edge[]:存储了边信息的边表集 
              int In[]:存储了顶点的入度信息 
              int first[]:指向以该顶点为弧尾的第一条边 
              int n:顶点个数 
    输出变量:用来存储拓扑序列的字符串
    返回值:int :拓扑排序成功返回真。若存在环则返回假
    */ 
    int TopoLogicalSort(char *topo, EdgeLib edge[], int In[], int first[], int n)
    {
    int i, u, front, rear;

    front = rear = 0;
    for (i=0; i<MAXM; i++)//将入度为0的顶点入栈 
    {
    if (book[i] != 0 && In[i] == 0)
    {
    topo[rear++] = i + 'a';
    }
    }

    while (front < rear)//採用广度优先搜索获取拓扑序列 
    {
    u = topo[front++] - 'a';
    for (i=first[u]; i!=-1; i=edge[i].next)
    {
    if (--In[edge[i].v] == 0)
    topo[rear++] = edge[i].v + 'a';
    }
    }
    topo[rear] = '';

    return (rear == n);//假设count小于顶点数。说明存在环 
    }


    int IsTopoSeq(char *data, char *topo)//依据关系列表data。推断topo字符串是否为拓扑序列 
    {
    int pos[MAXM] = {0};
    int i;

    for (i=0; topo[i]!=''; i++)//读取变量下标
    pos[topo[i]-'a'] = i;

    for (i=0; data[i]!=''; i+=2)//每次读取两个变量  
    {
    if (pos[data[i]-'a'] > pos[data[i+1]-'a'])
    return false;
    }

    return true;
    }

  • 相关阅读:
    光学字符识别OCR-6 光学识别
    光学字符识别OCR-5 文本切割
    光学字符识别OCR-4
    光学字符识别OCR-3
    leetcode 7 Reverse Integer(水题)
    leetcode 1 Two Sum(查找)
    DFS的简单应用(zoj2110,poj1562)
    Havel-Hakimi定理(握手定理)
    zoj1360/poj1328 Radar Installation(贪心)
    饶毅:做自己尊重的人
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/7257150.html
Copyright © 2011-2022 走看看