数据结构知识--关于图的创建及其应用,打印其深度遍历、广度遍历结果

第一关:创建采用邻接表存储的无向图

邻接表
对于图中每个顶点 vi,把所有邻接于 vi的顶点(对有向图是将从vi出发的弧的弧头顶点链接在一起)链接成一个带头结点的单链表,将所有头结点顺序存储在一个一维数组中。
例:下面左图G2对应的邻接表如右边所示。
在这里插入图片描述

/* 创建采用邻接表存储的无向图  实现文件    /
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ALGraph.h"
int visited[MAXVEX]; /*设访问标志数组为全局变量*/
void CreateUDG_ALG(ALGraph *g) /*构造无向图的邻接表*/
{    
// 请在这里补充代码,完成本关任务 
 /********** Begin *********/    
 if(g==NULL)  return;   
 int i , j , k , vnum , edgenum;    
 ENode *p;       
 scanf("%d%d%d",&g->kind,&vnum,&edgenum);       
 g->vexnum = vnum;    //结点个数       
 g->edgenum = edgenum;   //边的条数            
 for(i=0; i <vnum ;i++)            
 {          
 g->vertices[i].vex  = i ;                    
 g->vertices[i].firstarc =  NULL;        
 } //初始化顶点表               
 for(i=0;i<edgenum;i++)          //无向图具有双向连接的特点         
 {             
 scanf("%d%d",&j,&k);             
 p = ( ENode*)malloc(sizeof( ENode));             
 p->adjvex = k ;            
  p->nextarc = g->vertices[j].firstarc;    //头插法插入             
  g->vertices[j].firstarc = p ;
  p = ( ENode*)malloc(sizeof( ENode));     //头插法插入            
  p->adjvex = j ;             
  p->nextarc = g->vertices[k].firstarc;             
  g->vertices[k].firstarc = p ;
    }
   /********** End **********/ }
void PrintAdjList(ALGraph g) /*输出邻接表*/
{    int i,w;ENode *p;    
for(i=0;i<g.vexnum;i++)    
{        
printf("%d",g.vertices[i].vex);       
p=g.vertices[i].firstarc;        
while(p)       
 {            
  w=p->adjvex;           
  printf("->%d",w);            
  p=p->nextarc;        
  }       
   printf("\n");   
    }  
    }

测试输入:
2 5 6 //图的类型为2表示UDG,图的顶点数为5,图的边数为6
0 1 0 3 1 2 1 4 2 3 2 4 //输入各条边的两顶点的编号,按顶点编号从小到大的顺序输入
预期输出:
0->3->1
1->4->2->0
2->4->3->1
3->2->0
4->2->1

第2关:图的深度优先遍历

设初始时,图中所有顶点未曾被访问过:
● 从图中某个顶点 v 出发,访问此顶点;
● 依次从 v 的未被访问的邻接点出发深度优先遍历图,直至图中所有和顶点 v 有路径相通的顶点都被访问到;
● 如果此时图中还有尚未访问的顶点,则另选一个尚未访问的顶点作起始点,重复上述过程,直至图中所有顶点都被访问到为止。

/* 图的深度优先遍历  实现文件    */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ALGraph.h"
int visited[MAXVEX]; /*设访问标志数组为全局变量*/
void DFSTraverse(ALGraph  g)/*深度优先遍历以邻接表存储的图g*/
 {   
  int i;    
  for(i=0;i<g.vexnum;i++) /*访问标志数组初始化*/        
  visited[i]=0;    
  for(i=0;i<g.vexnum;i++)        
  if(!visited[i]) DFS(g,i); /*对尚未访问的顶点调用DFS函数*/
  }
  void DFS(ALGraph  g, int i)/*从未被访问的顶点Vi出发深度优先遍历图g*/ 
  {    
  // 请在这里补充代码,完成本关任务   
  /********** Begin *********/          
  ENode *p ;   //表结点类型的指针           
  if(visited[i]==1) return ;   //如果第i各节点已经被访问过,则返回          
  printf("%d ",i) ;          
  visited[i] = 1;          
  p = g.vertices[i].firstarc ;          
  while(p && visited[p->adjvex]==1)             
  p = p->nextarc;                       
  if(p)            
  {              
  i = p->adjvex ;             
  DFS(g ,i);          
  }
   /********** End **********/    
   }
   void CreateUDG_ALG(ALGraph *g) /*构造无向图的邻接表*/
   {        
   int i,j,k;
   ENode *p;   
    //printf("请输入图的类型(0-3表示DG,DN,UDG,UDN)、顶点数、边数:\n");   
    scanf("%d%d%d",&g->kind,&g->vexnum,&g->edgenum);   
     for(i=0;i<g->vexnum;i++) /*构造头结点数组*/   
      {        
      g->vertices[i].vex=i;        
      g->vertices[i].firstarc=NULL; /*初始化头结点指针域为空*/    }    
      //printf("请按顶点编号从小到大的顺序输入各条边的两顶点:\n");   
       for(k=0;k<g->edgenum;k++) /*构造邻接表*/   
        {        
        scanf("%d%d",&i,&j); /*输入一条边所依附的两个顶点的编号*/       
         /*将顶点Vj插入到第i个单链表的表头,也就是用“头插法”建立一个单链表*/        p=(ENode *)malloc(sizeof(ENode)); /*生成表结点*/        
         p->adjvex=j; p->weight=0;        
         p->nextarc=g->vertices[i].firstarc; /*插入表结点*/        
         g->vertices[i].firstarc=p;        
         /*将顶点Vi插入到第j个单链表的表头,也就是用“头插法”建立一个单链表*/        
         p=(ENode *)malloc(sizeof(ENode));       
          p->adjvex=i; p->weight=0;        
          p->nextarc=g->vertices[j].firstarc;        
          g->vertices[j].firstarc=p;    
          }
     }

测试输入:
2 5 6
0 1 0 3 1 2 1 4 2 3 2 4
预期输出:
0 3 2 4 1 //深度优先遍历的结果

**

第3关:图的广度优先遍历

**
设初始时,图中所有顶点未曾被访问过:
● 从图中某个顶点 v 出发,访问此顶点;
● 依次访问 v 的各个未被访问的多个邻接点;
● 分别从这些邻接点出发依次访问它们的邻接点,并使 “先被访问顶点的邻接点” 先于 “后被访问顶点的邻接点” 被访问,直至图中所有已被访问的顶点的邻接点都被访问

/* 图的广度优先遍历  实现文件    */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ALGraph.h"
int visited[MAXVEX]; /*设访问标志数组为全局变量*/
void BFSTraverse(ALGraph g) 
{
/*广度优先遍历以邻接表存储的图g,由于BFS要求”先被访问的顶点的邻接点也先被访问”,故需借助队列Q实现*/   
 // 请在这里补充代码,完成本关任务   
  /********** Begin *********/    
  int i;      
  SeqQueue *Q = (SeqQueue *)malloc(sizeof(SeqQueue));   //创建队列
    for (i=0; i<g.vexnum; ++i){   /*访问标志数组初始化*/        
    visited[i] = 0;    
     }     
   InitQueue(Q);      //队列的初始化        
   for (i=0; i<g.vexnum; ++i){          
   if(!visited[i]){     //如果第i个结点没有被访问            
   visited[i] = 1;             
   printf("%d ", g.vertices[i].vex);              
   EnQueue(Q, i);       //将元素x入队
  while (Q->len!=0){    //当队列不为空时,或者 Q->front != Q->rear
  DeQueue(Q, &i);     //将队头元素出队                                  
  ENode *p = g.vertices[i].firstarc;                  
  while (p){                     
  if (!visited[p->adjvex]){                          
  visited[p->adjvex] = 1;                          
  printf("%d ", g.vertices[p->adjvex].vex);                          
  EnQueue(Q, p->adjvex);     //将元素x入队                  
    }                      
    p = p->nextarc;                 
           }          
         }       
      }   
  }       
  /********** End **********/     }  
void InitQueue(SeqQueue *q)//队列的初始化{    
q->front=q->rear=0;    
q->len=0;}int QueueEmpty(SeqQueue q)//判队空
{    
if(q.len==0)return 1;    
else return 0; 
}
void EnQueue(SeqQueue *q, datatype x)//将元素x入队
{    
if(q->len==MAXSIZE)//判队满   
 {        
 printf("Queue is full\n");return;  
   }    
   q->data[q->rear]=x; 
   q->rear=(q->rear+1)%MAXSIZE;    
   q->len++;
   }
   void DeQueue(SeqQueue *q, datatype *x)//将队头元素出队
   {   
    if(q->len==0)//判队空  
      {     
         printf("Queue is empty\n");return;  
        }   
    *x=q->data[q->front];
     q->front=(q->front+1)%MAXSIZE;   
     q->len--;
     }
void CreateUDG_ALG(ALGraph *g) /*构造无向图的邻接表*/
{       
 int i,j,k;ENode *p;   
  //printf("请输入图的类型(0-3表示DG,DN,UDG,UDN)、顶点数、边数:\n");    scanf("%d%d%d",&g->kind,&g->vexnum,&g->edgenum);    
  for(i=0;i<g->vexnum;i++) /*构造头结点数组*/  
    {       
    g->vertices[i].vex=i;      
    g->vertices[i].firstarc=NULL; /*初始化头结点指针域为空*/  
     }    //printf("请按顶点编号从小到大的顺序输入各条边的两顶点:\n");      for(k=0;k<g->edgenum;k++) /*构造邻接表*/  
     {        
     scanf("%d%d",&i,&j); /*输入一条边所依附的两个顶点的编号*/        
     /*将顶点Vj插入到第i个单链表的表头,也就是用“头插法”建立一个单链表*/        p=(ENode *)malloc(sizeof(ENode)); /*生成表结点*/        
p->adjvex=j; p->weight=0;        
p->nextarc=g->vertices[i].firstarc; /*插入表结点*/        
g->vertices[i].firstarc=p;        
/*将顶点Vi插入到第j个单链表的表头,也就是用“头插法”建立一个单链表*/        p=(ENode *)malloc(sizeof(ENode));        
p->adjvex=i; p->weight=0;        
p->nextarc=g->vertices[j].firstarc;        
g->vertices[j].firstarc=p; 
   }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值