广度优先遍历,深度优先遍历,拓扑排序(十字链表存储结构)

来源:互联网 发布:淘宝李宁三号店 是高仿 编辑:程序博客网 时间:2024/06/02 07:30

 

创建的有向图为:{6条边,8个顶点}<1,2><1,3><1,4><3,2><3,4><4,5><6,4><6,5>

 

 

 

#include<stdio.h>

/*==============================十字链表的存储结构===========================*/
#define  MAX_VERTEX_NUM     20
#define  QUEUE_MAXSIZE      100
#define  MAXSTACK           100

int top=-1;
int visited[MAX_VERTEX_NUM];
int indegree[MAX_VERTEX_NUM];

typedef int  VRType;
typedef int  VertexType;

struct ArcBox {
   int      tailvex,headvex;
   struct ArcBox *hlink,*tlink;
   VRType   weight;
};

struct VexNode {
  VertexType    data;
  struct ArcBox  *firstin,*firstout;
};

typedef struct {
  struct VexNode  xlist[MAX_VERTEX_NUM];
  int vexnum,arcnum;
}OLGraph;


struct stack {
   int    ivex;
}stack[MAXSTACK],mythis;
#define pop     stack[top--]
#define push(s) stack[++top] = (s)


/*============================================================================*/
/*                                                                            */
/*                         顺   序   队  列                                   */
/*                                                                            */
/*============================================================================*/
typedef struct{
    int data;
}elemtype;

typedef struct{
    elemtype elem[QUEUE_MAXSIZE];
    int front ,rear;
    int length;
}QUEUE;

void queue_init(QUEUE *q)
{
   (*q).front=(*q).rear=-1; (*q).length=0;
}

int queue_empty(QUEUE *q)
{
   if((*q).length==0) return 1;
   else               return 0;
}

void queue_push(QUEUE *q,elemtype e)
{
   if((*q).length==QUEUE_MAXSIZE) { printf("QUEUE IS FULL"); return ;}
   (*q).rear=++(*q).rear%QUEUE_MAXSIZE;
   (*q).elem[(*q).rear]=e;
   (*q).length++;
   if((*q).length==1&&(*q).front==-1) (*q).front=0;
}

void queue_pop(QUEUE *q,elemtype *e)
{
   if((*q).length==0) { printf("QUEUE IS EMPTY"); return ;}
   *e=(*q).elem[(*q).front++];
   (*q).front=(*q).front%QUEUE_MAXSIZE;
   (*q).length--;
   if((*q).length==0) (*q).front=(*q).rear=-1;
}

/*============================十字链表的基本操作=============================*/

int LocateVex(OLGraph *G,VertexType v)   /*确定顶点V的存储位置*/
{
  int i;
  for(i = 0;i < G->vexnum;i ++)
    if(v == (G->xlist[i]).data )
       return i;
}

/*返回ivex第一个邻接顶点的位置*/
int FirstAdjVex(OLGraph *G,int ivex,int mark)
{
   int f_out,f_in;  /*mark==1 则返回顶点出度的第一个邻接点;否则,返回入度的第一个邻接点*/
   struct ArcBox  *out,*in;
   if(1 == mark)
   {
     out = G->xlist[ivex].firstout;
     if(out != NULL) f_out = ((ivex == out->tailvex)?(out->headvex):(out->tailvex));
     else            f_out = -1;
     return f_out;
   }
   else
   {
     in = G->xlist[ivex].firstin;
     if(in != NULL) f_in = (ivex == in->tailvex)?(in->headvex):(in->tailvex);
     else           f_in = -1;
     return f_in ;
   }
}

/*返回ivex相对于wvex的下一个邻接顶点的位置*/
int NextAdjVex(OLGraph *G,int ivex ,int wvex,int mark)
{
   int f_out,f_in,temp; /*mark==1 则返回顶点出度的下一个邻接点;否则,返回入度的下一个邻接点*/
   struct ArcBox  *out,*in;
   if(1 == mark)
   {   /*返回顶点ivex的出度相对于wvex的下一个邻接点*/
      out = G->xlist[ivex].firstout;
      if(out != NULL)
      {
         while(out != NULL )
         {
           temp=( (ivex == out->tailvex) ? (out->headvex) : (out->tailvex) );
           if(wvex == temp)
            {
              out = out->tlink;
              if(out != NULL) f_out = (ivex == out->tailvex)?(out->headvex):(out->tailvex);
              else            f_out = -1;
              return f_out;
            }
           out = out->tlink;
        }/*while*/
      }
      else { f_out= -1;  return f_out;}
   }
   else
   {    /*返回顶点ivex的入度相对于wvex的下一个邻接点*/
      in = G->xlist[ivex].firstin;
      if(in != NULL)
      {
         while(in != NULL )
         {
           temp=( (ivex == in->tailvex) ? (in->headvex) : (in->tailvex) );
           if(wvex == temp)
           {
              in = in->hlink;
              if(in != NULL) f_in = (ivex == in->tailvex)?(in->headvex):(in->tailvex);
              else           f_in = -1;
              return f_in;
           }
           in = in->hlink;
         }/*while*/
      }
      else{ f_in = -1; return f_in; }

   }
}

/*--------------------------11、深度优先遍历---------------------------------*/
/* int visited[MAX_VERTEX_NUM] */
void VisitFunc(OLGraph *G,int ivex)
{
  printf("%6d",G->xlist[ivex].data);

}

void DFS( OLGraph *G,int i_vex )
{
   int w_vex;
   int mark=1;  /* 求有向图的强连通分量时用,逆向遍历,mark=1为出度标志,mark=0否则为入度标志*/
   visited[i_vex] = 1; VisitFunc(G,i_vex);
   for(w_vex = FirstAdjVex(G,i_vex,mark); w_vex>=0; w_vex=NextAdjVex(G,i_vex,w_vex,mark) )
     if(!visited[w_vex])  DFS(G,w_vex);
}

void DFSTraverse( OLGraph *G )
{
   int i_vex;
   for(i_vex = 0; i_vex < G->vexnum; i_vex ++) visited[i_vex] = 0;
   for(i_vex = 0; i_vex < G->vexnum; i_vex ++)
     if(!visited[i_vex]) DFS(G,i_vex);
}

/*-------------------------- 12、广度优先遍历----------------------------------*/
void BFSTraverse(OLGraph *G)
{
  int i_vex,u_vex,w_vex,mark=1;
  elemtype e1,e2,e3;
  QUEUE Q;

  for(i_vex = 0; i_vex < G->vexnum;i_vex ++)  visited[i_vex] = 0;
  queue_init(&Q);

  for(i_vex = 0;i_vex < G->vexnum;i_vex ++)
    if(!visited[i_vex])
    {
      visited[i_vex]=1; VisitFunc(G,i_vex);
      e1.data = i_vex;
      queue_push(&Q,e1);

      while(!queue_empty(&Q))
      {
        queue_pop(&Q,&e2); u_vex = e2.data;
        for(w_vex = FirstAdjVex(G,u_vex,mark);w_vex >= 0;w_vex = NextAdjVex(G,u_vex,w_vex,mark))
         if(!visited[w_vex])
         {
            visited[w_vex]=1;VisitFunc(G,w_vex);
            e3.data =w_vex;queue_push(&Q,e3);
          }/* if */
      }/* while */
  }/* if */
}
/*===============================拓扑排序AOV=================================*/
void FindDegree(OLGraph *G)
{
   int ivex,in_count;
   struct ArcBox  *in;
   for(ivex = 0;ivex < G->vexnum;ivex ++)
   {
     in_count=0;
     in = G->xlist[ivex].firstin;
     while(in != NULL ){ in_count++; in = in->hlink;}/*while*/
     indegree[ivex] = in_count;
   }
}


int TopologicalSort(OLGraph *G)
{
   int i,count,v,w,mark=1;
   struct stack intemp;
   FindDegree(G);
   top=-1;
   for(i=0;i<G->vexnum;i++)
     if(!indegree[i]) { mythis.ivex = i; push(mythis); }
   count = 0;
   while(-1 != top)
   {
      mythis = pop; printf("%6d",G->xlist[mythis.ivex].data);   ++count;
      for(w = FirstAdjVex(G,mythis.ivex,mark);w>= 0;w = NextAdjVex(G,mythis.ivex,w,mark))
        if(!(--indegree[w])){ intemp.ivex = w; push(intemp); }
   }
   if(count < G->vexnum)  return  0;
   else                   return  1;
}


/*==========================================================================*/

int CreateDN(OLGraph *G)                /*创建十字链表*/
{
   int i,j,k;
   VRType weight=0;
   VertexType v1,v2;
   struct ArcBox *p;

   printf("/n Orthogonal List Create DG/n");
   printf("/n/n The Graph's number of Vertex :"); scanf("%d",&(G->vexnum));
   printf(" The Graph's number of Arcnum :"); scanf("%d",&(G->arcnum));
   printf("/n");
   for(i=0;i<G->vexnum;i++) {
      printf(" The Graph's %d Vertex's NAME:",i+1); scanf("%d",&(G->xlist[i].data));
      G->xlist[i].firstin = NULL;
      G->xlist[i].firstout = NULL;
   }

   for(k=0;k<G->arcnum;k++)
   {
     printf("/n The %d Arc ./n",k+1);
     printf(" The tail vertex:");do{ scanf("%d",&v1);if((v1<=0)||(v1>G->vexnum))printf(" ERROR/n The tail vertex:"); }while((v1<=0)||(v1>G->vexnum));
     printf(" The head vertex:");do{ scanf("%d",&v2);if((v2<=0)||(v2>G->vexnum))printf(" ERROR/n The head vertex:"); }while((v2<=0)||(v2>G->vexnum));
     /*printf(" The arc  weight:");do{ scanf("%d",&weight); if(weight < 0) printf(" ERROR/n The arc  weight:"); }while(weight < 0);*/

     i = LocateVex(G,v1); j = LocateVex(G,v2);
     p = (struct ArcBox *)malloc(sizeof(struct ArcBox));
     p->tailvex = i;
     p->headvex = j;
     p->hlink = G->xlist[j].firstin;
     p->tlink = G->xlist[i].firstout;
     p->weight = weight;
     G->xlist[j].firstin = G->xlist[i].firstout = p;
   }
   return 0;
}

void Prin_OLGraph(OLGraph *G)           /*输出十字链表*/
{
   int k;
   struct ArcBox *p;

   printf("/n/n The Vertex Outdegree =>/n/n");
   for(k = 0;k <G->vexnum;k ++)
   {
      p = G->xlist[k].firstout;
      printf("  /tVertex %d :",k+1);
      while( p != NULL ){  printf(" (%d,%d) ",1+p->tailvex,1+p->headvex);   p = p->tlink; }
      printf("/n");
   }

   printf("/n/n The Vertex Indegree =>/n/n");
   for(k = 0;k <G->vexnum;k ++)
   {
      p = G->xlist[k].firstin;
      printf("  /tVertex %d :",k+1);
      while( p != NULL ){  printf(" (%d,%d) ",1+p->tailvex,1+p->headvex);   p = p->hlink; }
      printf("/n");
   }
}

/*============================================================================*/
int main()
{
   int out,next_out;
   OLGraph G;
   CreateDN(&G);
   Prin_OLGraph(&G);

   printf("/n DFSTraverse AMGraph:/n");
   DFSTraverse(&G);
   printf("/n BFSTraverse AMGraph:/n");
   BFSTraverse(&G);
   printf("/n TopologicalSort AMGraph:/n");
   TopologicalSort(&G);

   getch();
}