图,图的遍历

输入图的类型、顶点数、狐(边)数、顶点信息、狐(边)信息,建立相应的图(具体类型为有向图、无向图,采用邻接矩阵存储结构);分别按深度优先搜索和广度优先搜索遍历图;按某种形式输出图及遍历结果

#include <stdio.h>   
#include <stdlib.h>
#define OVERFLOW -2         
#define ILLEGAL -1         
#define OK 1                
#define ERROR 0
#define MAXQSIZE 100        //队列的最大长度 
typedef int QElemType;
typedef int Status;       
typedef float ElemType;
//-------------图的数组(邻接矩阵)存储表示------------------------------------- 
#define INFINITY        65535     //最大值 ∞
#define MAX_VERTEX_NUM  20          //最大顶点个数
typedef enum {DG,UDG} GraphKind;  //(有向图,无向图)
typedef int VRType;
typedef int VertexType;
typedef struct ArcCell{
 VRType   adj;   //VRType是顶点关系类型。对无权图,用1或0,表示相邻与否,对带权图,则为权值类型 
}ArcCell,AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM]; 
typedef struct{
 VertexType vexs[MAX_VERTEX_NUM];    //顶点向量
 AdjMatrix  arcs;     //邻接矩阵
 int vexnum,arcnum;   //图当前的定点数和弧数
 GraphKind  kind;     //图的种类标志 
}MGraph; 
//------------------图的创建------------------------------------------------------- 
int LocateVex(MGraph G, int v){  //顶点定位函数 
 for(int i=0; i<=G.vexnum; ++i)
  if(G.vexs[i]==v)  
      return i;  //若找到结点返回i 
 return -1;  //否则返回-1,表示没有找到 
}
Status CreateDG(MGraph &G){
 //采用数组(邻接矩阵)表示法,构造有向图G 
 VertexType v1,v2;
 int i,j;
 printf("请依次输入有向图G的顶点数,弧数,用空格隔开\n");
 scanf("%d %d",&G.vexnum,&G.arcnum);
 printf("请依次输入有向图G的顶点名称,用空格隔开\n"); 
 for(int i=0;i<G.vexnum;++i)
  scanf("%d",&G.vexs[i]);   //构造各顶点向量 
 for(int i=0;i<G.vexnum;++i)
     for(int j=0;j<G.vexnum;++j)
      G.arcs[i][j].adj=0; 
 printf("请依次输入有向图G每条弧依附的两顶点名称,输完一组按回车\n"); 
 for(int k=0;k<G.arcnum;++k){ //构造邻接矩阵 
     scanf("%d",&v1);
        scanf("%d",&v2);
     i=LocateVex(G,v1);
  j=LocateVex(G,v2);     //确定v1,v2在G中的位置 
  G.arcs[i][j].adj=1;
 }//for
 return OK; 
}
Status CreateUDG(MGraph &G){
 //采用数组(邻接矩阵)表示法,构造无向图G 
 VertexType v1,v2;
 int i,j;
 printf("请依次输入无向图G的顶点数,弧数,用空格隔开\n");
 scanf("%d %d",&G.vexnum,&G.arcnum);
 printf("请依次输入无向图G的顶点名称,用空格隔开\n"); 
 for(int i=0;i<G.vexnum;++i)
  scanf("%d",&G.vexs[i]);   //构造各顶点向量 
 for(int i=0;i<G.vexnum;++i)
     for(int j=0;j<G.vexnum;++j)  //预置邻接矩阵 
      G.arcs[i][j].adj=0; 
 printf("请依次输入无向图G每条弧依附的两顶点名称,输完一组按回车\n"); 
 for(int k=0;k<G.arcnum;++k){ //构造邻接矩阵 
     scanf("%d",&v1);
        scanf("%d",&v2);
     i=LocateVex(G,v1);
  j=LocateVex(G,v2);     //确定v1,v2在G中的位置 
  G.arcs[i][j].adj=1;
  G.arcs[j][i]=G.arcs[i][j];  //置<v1,v2>的对称弧<v2,v1> 
 }//for
 return OK; 
}
Status CreateGraph(MGraph &G){  //总函数 
 //采用数组(邻接矩阵)表示法,构造图G
 printf("请输入您想构造的图的类型:有向图,无向图,分别对应0,1):");
 int temp; 
 scanf("%d",&temp);  //输入所要构造图的类型
 G.kind=(GraphKind)temp;
 switch((GraphKind)temp){
  case  DG:  return CreateDG(G);  //构造有向图G
  case UDG:  return CreateUDG(G); //构造无向图G
  default :  return ERROR;
 } 
}
//--------------------------邻接矩阵的输出 ----------------------------------------------
Status PrintAdjMatrix(MGraph G){  //打印某个图的邻接矩阵 
 //采用数组(邻接矩阵)表示法,构造图G
 for(int i=0;i<G.vexnum;i++){
  for(int j=0;j<G.vexnum;j++)
       printf(" %3d ", G.arcs[i][j].adj);
     printf("\n\n");
 }  
}
//------------------------------------3.图的遍历 ----------------------------------------------
int FirstAdjVex(MGraph G,VertexType v){
 //求顶点v在图G中的第一个邻接点
 int i,j=0,k;
 k=LocateVex(G,v);  //v是顶点,不是序号!需要定位 
 for(i=0;i<G.vexnum;++i)
    if(G.arcs[k][i].adj!=j)
        return i;       //若找到则返回i 
 return -1;             //若未找到返回-1 
}//FirstAdjVex
int NextAdjVex(MGraph G,VertexType v,VertexType w){
 //求顶点v在图G中相对于邻接点w的下一个邻接点 
 int i,j=0,k1,k2;
 k1=LocateVex(G,v);  //v是顶点,不是序号!需要定位  
 k2=LocateVex(G,w);  //w是顶点,不是序号!需要定位 
 for(i=k2+1;i<G.vexnum;++i)
    if(G.arcs[k1][i].adj!=j)
        return i;       //若找到则返回i 
 return -1;             //若未找到返回-1  
}//NextAdjVex
//-----------------------深度优先遍历DFS-----------------------------
typedef enum { TRUE=1 , FALSE=0 } Boolean; 
Boolean visited[MAX_VERTEX_NUM];    //访问标志数组 
Status (*VisitFunc)(int v);         //函数变量 
Status Print(int v){  //元素访问函数 
 printf(" %3d ",v);
 return OK;
}//Print
void DFSTraverse(MGraph G,Status (*Visit)(int v)){
 //对图G作深度优先遍历,调用Visit()函数访问结点
 void DFS(MGraph G,int v);  //函数声明 
 VisitFunc=Visit;         //使用全局变量VisitFunc,使DFS不必设函数指针参数 
 for(int v=0;v<G.vexnum;++v)
     visited[v]=FALSE;    //预置标志数组
 for(int v=0;v<G.vexnum;++v)
    if(!visited[v])   //若该顶点未被访问 
        DFS(G,v); 
}//DFSTraverse
void DFS(MGraph G,int v){
    //从第v个顶点出发递归地深度优先遍历图G
 visited[v]=TRUE;  //先将访问标志数组该元素的访问标志改为True 
 //注意,序号v从0开始,所以序号v总比第v个顶点在图中的位置少1 
 VisitFunc(G.vexs[v]);     //访问第v个顶点  注意:v是序号,不是顶点! 
 for(int w=FirstAdjVex(G,G.vexs[v]);w>=0;w=NextAdjVex(G,G.vexs[v],G.vexs[w])){  //v是序号,不是顶点!
  if(!visited[w])
      DFS(G,w);   //对v的尚未访问的邻接点w递归调用DFS 
 }//for
}//DFS
//------------------------广度优先遍历(BFS)----------------------------------------
//-------------------循环队列---------------------------------------- 
typedef struct              //循环队列的C语言描述 
{
 QElemType *base;        //初始化动态分配存储空间
 int front;              //头指针,若队列不空,指向队头元素 
 int rear;              //尾指针,若队列不空,指向队尾元素的下一个位置 
}SqQueue; 
//>>>>>>>>>>>>>>>>>>>>1.初始化循环队列<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Status InitQueue_Sq(SqQueue &Q) //初始化循环队列 
{   //构建一个空队列 Q
 if(!(Q.base=(QElemType *)malloc(sizeof(QElemType)))){  //申请内存空间,若失败则提示并退出程序
  printf("内存分配失败,程序即将退出!\n");
  exit(OVERFLOW);
 }
 Q.front=Q.rear=0;
 return OK;
}
//>>>>>>>>>>>>>>>>>>>2.销毁循环队列<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Status DestoryQueue_Sq(SqQueue &Q)
{   //销毁队列Q
 free(Q.base); 
 Q.base=NULL;
 printf("循环队列已成功销毁!\n");
 return OK;
}
//>>>>>>>>>>>>>>>>>>>3.判断链队列是否为空<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Status QueueEmpty_Sq(SqQueue Q)
{   //若Q为空队列,则返回OK;否则返回ERROR
 if(Q.rear==Q.front) //队列为空的标志 
  return OK; 
 else
     return ERROR; 
}
//>>>>>>>>>>>>>>>>>>>4.在链队列中插入元素(入队)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Status EnQueue_Sq(SqQueue &Q,QElemType e)
{   //插入元素e为Q的新的队尾元素e 
 if((Q.rear+1)%MAXQSIZE==Q.front)  //队列满
    return ERROR;
 Q.base[Q.rear]=e;
 Q.rear=(Q.rear+1)%MAXQSIZE;   //每插入一个新队尾元素,尾指针增一 
 return OK; 
}
//>>>>>>>>>>>>>>>>>>5.在链队列中删除元素(出队)<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
Status DeQueue_Sq(SqQueue &Q,QElemType &e)
{   //若队列不空,则删除Q的队头元素,用e返回其值,并返回OK,否则返回ERROR
 if(Q.front==Q.rear) //判空
       return ERROR;
 e=Q.base[Q.front];
 Q.front=(Q.front+1)%MAXQSIZE;  //每当删除队头元素时,头指针增1 
 return OK; 
} 
void BFSTraverse(MGraph G,Status (*Visit)(int v)){
 //按广度优先非递归遍历图G,使用辅助队列Q和访问标志数组visited
 SqQueue Q; 
 for(int v=0;v<G.vexnum;++v)
     visited[v]=FALSE;     //预置标志数组
 InitQueue_Sq(Q);          //置空辅助队列Q
 for(int v=0;v<G.vexnum;++v)
  if(!visited[v]){        //v尚未访问 
   visited[v]=TRUE;  
   Visit(G.vexs[v]);   //访问第v顶点
   EnQueue_Sq(Q,v);    //v入队列 
   while(!QueueEmpty_Sq(Q)){    //队列不空 
    DeQueue_Sq(Q,v);      //队头元素出队并置为u
    for(int w=FirstAdjVex(G,G.vexs[v]);w>=0;w=NextAdjVex(G,G.vexs[v],G.vexs[w])){ 
         if(!visited[w]){  //w为v尚未访问的邻接顶点 
           visited[w]=TRUE;  
                 Visit(G.vexs[w]);   //访问第w顶点 
      }//if 
    }//for 
   }//while 
  }//if
}//BFSTraverse
//-------------------------------主函数-------------------------------
int main(int argc,char *argv[]){
 MGraph G; 
 CreateGraph(G);      //图的创建
 printf(" 图的邻接矩阵:\n\n"); 
 PrintAdjMatrix(G);   //打印邻接矩阵 
 printf("图的遍历:\n");
 printf("深度优先遍历结果:");
 DFSTraverse(G,Print);
 printf("\n广度优先遍历结果:");
 BFSTraverse(G,Print); 
 return 0;
} 
  • 8
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值