有向图的拓扑有向序列

来源:互联网 发布:淘宝与网站合作方案 编辑:程序博客网 时间:2024/04/29 16:29

#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include<conio.h>
#include<iostream>
#define MAX_VERTEX_NUM 20 /*最大顶点数*/
#define INFINITY 32767    /*最大值*/
#define STACK_INIT_SIZE 100    //栈的最大空间
#define STACKINCREMENT 20    //栈的追加空间单位
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define OUTPLACE -1
typedef int  Status;
typedef int  VertexType;
typedef int  InfoType;
typedef int  SElemType;

typedef struct{
 SElemType *base;   /*栈底指针*/
 SElemType *top;    /*栈顶指针*/
 int stacksize;     /*栈的大小*/
}SqStack;

typedef struct ArcNode{
  int              adjvex;   /*该弧所指向的顶点的位置*/
  struct ArcNode   *nextarc;    /*指向一下条弧的指针*/
  InfoType         info;     /*该弧相关信息*/
}ArcNode;

typedef struct VNode{
    VertexType    data;   /*顶点信息*/
    ArcNode       *firstarc;   /*指向第一条依附该顶点的弧的指针*/
}VNode,AdjList[MAX_VERTEX_NUM];

typedef struct{
    AdjList   vertices;
    int       vexnum,arcnum;     /*图当前的顶点数和弧数*/
    int       kind;              /*图的种类标志*/
}ALGraph;

int indegree[MAX_VERTEX_NUM];

Status InitStack(SqStack &S)        //初始化栈
{
 S.base=(SElemType *)malloc(STACK_INIT_SIZE*sizeof(SElemType));
 if(!S.base) exit(OVERFLOW);
 S.top=S.base;
 S.stacksize=STACK_INIT_SIZE;
 return OK;
}

Status GetTop(SqStack &S,SElemType &e)    //取栈顶元素
{
 if(S.top==S.base) return ERROR;
 e=*(S.top-1);
 return OK;
}

Status Push(SqStack &S,SElemType e1)      //进栈操作
{
 if(S.top-S.base>=S.stacksize){
  S.base=(SElemType *)realloc(S.base,
    (S.stacksize+STACKINCREMENT)*sizeof(SElemType));
  if(!S.base) exit(OVERFLOW);
  S.top=S.base+S.stacksize;
  S.stacksize+=STACKINCREMENT;
 }
 *S.top++=e1;
 return OK;
}

Status Pop(SqStack &S,SElemType &e)         //出栈操作
{
 if(S.top==S.base) return ERROR;
 e=*(--S.top);
 return OK;
}

Status StackEmpty(SqStack S)     //判空操作
{
   if(S.top==S.base)
    return 1;
   else
    return 0;
}

int LocateVex(ALGraph &G,VertexType v)      /*返回顶点v在G中下标*/
{
  int i;
  for(i=0;i<G.vexnum;i++)
    if(v==G.vertices[i].data)   return i;

  return -1;
}

ALGraph Build_ALG_DN()      /*创建一个有向网*/
{ ALGraph G;
  int i,j,k,v1,v2;
  ArcNode *p=NULL,*q=NULL;
  for(i=0;i<MAX_VERTEX_NUM;i++)
    G.vertices[i].firstarc=NULL;    /*初始化*/
  printf("请输入顶点数:");
  scanf("%d",&G.vexnum);       /*输入顶点数*/
  if(G.vexnum<0)
     {
       printf("错误/n");
       return G;
     }
  printf("请输入边数:");
  scanf("%d",&G.arcnum);    /*输入边数*/
  if(G.arcnum<0)
     {
       printf("错误/n");
       return G;
     }
  for(i=0;i<G.vexnum;i++)    /*输入顶点序列*/
    {
      printf("请输入顶点信息: ");
      scanf("%d",&G.vertices[i].data);
    }
  for(i=0;i<G.arcnum;i++)    /*输入边的信息*/
    {
      printf("请输入边的信息(v1,v2):");
      scanf("%d,%d,%d",&v1,&v2);
      j=LocateVex(G,v1),k=LocateVex(G,v2);   /*获取v1和v2在G中的位置*/
      if(j<0||k<0||j==k)
        {
          printf("ERROR!!/n");
          i--;continue;
        }  /*  如果顶点输入错误,继续     */
      p=(ArcNode *)malloc(sizeof(ArcNode));     /*分配结点*/
      p->adjvex=k;   p->nextarc=NULL;
      if(!G.vertices[j].firstarc)  G.vertices[j].firstarc=p;     /*p是v1的第一条弧*/
      else {
        for(q=G.vertices[j].firstarc;q->nextarc;q=q->nextarc);   /*找到链表的最后一个结点*/
        q->nextarc=p;
        }
     
    }
  return G;
}

Status Insert_Vertex_ALGraph(ALGraph &G)     /*插入一个顶点*/
{
  char a;
  char c;
  c='y';
  while(c=='y')
  {
    printf("请输入顶点信息:");
    scanf("%d",&a);
    G.vertices[G.vexnum++].data=a;              /*插入顶点,顶点数加1*/
    printf("你还要插入顶点吗?(y/n)?");
    scanf("%s",&c);
  }
  return OK;
}

Status Insert_Arc_ALGraph(ALGraph &G)  /*插入一条边*/
{
  int j,k;
  char v1,v2,c;
  ArcNode *p,*q;
  c='y';   
  while(c=='y')              /*判断是否插入边*/
  {
     printf("请输入边的信息(v1,v2):");
     scanf("%d,%d,%d",&v1,&v2);             /*输入边的信息(顶点)*/
     j=LocateVex(G,v1);  k=LocateVex(G,v2);
     if(j<0||k<0||j==k){printf("ERROR!!/n");   continue;}    /*如果顶点不属于G,继续*/
     p=(ArcNode *)malloc(sizeof(ArcNode));     /*分配一个结点*/
     p->adjvex=k;  p->nextarc=NULL;
     if(!G.vertices[j].firstarc)  G.vertices[j].firstarc=p;  /*如果v1没有边,插入为第一条边*/
     else                                           /*如果v1有边,将新边插到最后一个结点后*/
     {
       for(q=G.vertices[j].firstarc;q->nextarc;q=q->nextarc);
         q->nextarc=p;
     }
  G.arcnum++;
     printf("你还要插入边吗?(y/n)");
     scanf("%s",&c);
  }
  return OK;
}
Status FindInDegree(ALGraph G,int indegree[])   //对有向图的各个顶点求入度
{
  int i,k;
  ArcNode *p;
  for(i=0;i<G.vexnum;i++)
  {
   if(G.vertices[i].firstarc)   
   {
    p=G.vertices[i].firstarc;
    k=p->adjvex;
    indegree[k]=1;
    while(p->nextarc)
    {
     p=p->nextarc;
     k=p->adjvex;
     ++indegree[k];
    }//while
   }//if
  }//for
  return OK;
}
Status TopologicalSort(ALGraph &G)
{    //输出有向图无环图的拓扑有向序列,若有回路,返回错误。
   int i,count,k;
  
   ArcNode *p;
   SqStack S;
   FindInDegree(G,indegree);    //对各顶点求入度
   InitStack(S);
   for(i=0;i<G.vexnum;i++)
    if(!indegree[i])   Push(S,i);   //0入度顶点进栈
   count=0;
   while(!StackEmpty(S))   //栈非空
   {
    Pop(S,i);
    printf("  %d   ",G.vertices[i].data);
    count++;  //输出i号顶点,计数加一
    for(p=G.vertices[i].firstarc;p;p=p->nextarc)
    {
     k=p->adjvex;
     if(!(--indegree[k]))   Push(S,k);  //i号顶点的每一个邻接点入度减一,若减后为零,入栈
    }//for
   }//while
   if(count<G.vexnum)   return ERROR;    //如果输出的顶点数小于图的顶点数,则有向图内有环,返回错误
   else    return OK;
}

 

int main()
{
  int i;
  int c=1;
  ALGraph G;
  ArcNode *p;
  printf("本程序将建立一个用邻接表方式存储的有向图,可以进行插入顶点或边的操作,/n可以输出有向图的信息或输出该有向图的拓扑有向序列。/n请按任意键继续/n");
  getch();
  system("cls");
  printf("1.创建有向图:(第一次请先执行这一步!)/n");
  system("cls");
  printf("========创建有向图==========/n");
  printf("所有的输入都为整数,边的输入方式为输入该边由哪个顶点指向哪个顶点,/n两个顶点用“,”隔开。/n");
  G=Build_ALG_DN();
  printf("请按任意键继续选择操作。/n");
  getch();
  while(c!=0)
  {  
   system("cls");
   printf("1.插入顶点/n");
   printf("2.插入边/n");
   printf("3.输出有向图的信息(顶点和边)/n");
   printf("4.输出有向图的拓扑有向序列/n");
   printf("0.退出/n");
   printf("请选择你要进行的操作:");
   scanf("%d",&c);
   switch(c)
   {
    case 1:
     system("cls");
     printf("========插入顶点===========/n");
           Insert_Vertex_ALGraph(G);   /*插入顶点*/
     printf("请按任意键继续选择操作。/n");
     getch();
     break;
       case 2:
     system("cls");
     printf("========插入边==========/n");
     Insert_Arc_ALGraph(G);     //插入边
     printf("请按任意键继续选择操作。/n");
     getch();
     break;
    case 3:
     system("cls");
     printf("========输出有向图=========/n");
           for(i=0;i<G.vexnum;i++)     //输出顶点的信息
     {
              printf("%d  ",G.vertices[i].data);
     }
     printf("/n");
           for(i=0;i<G.vexnum;i++)  //输出边的信息
     {
              for(p=G.vertices[i].firstarc;p;p=p->nextarc)
              printf("%d-->%d  ",G.vertices[i].data,G.vertices[p->adjvex].data);
     }
           printf("/n");
           printf("/n请按任意键继续选择操作。/n");
     getch();
     break;
    case 4:
     system("cls");
     printf("========输出有向图的拓扑有向序列===========/n");
     if(!TopologicalSort(G))
      printf("/n有向图中有回路,错误/n");
     printf("/n请按任意键继续选择操作。/n");
     getch();
     break;
    case 0:
     break;
    default:
     printf("/n你的选择是错误的!/n");
     getch();
     break;
   }//switch
  }//while
  printf("/n欢迎下次再来……^_^/n");
  getch();
  return 0;
}

 

我是大三的计算机方面专业的学生,

请大家指点……