C/C++代码实现图(有向图)的深度,广度优先遍历

<一>深度优先搜索(Depth-First Search—DFS)是指按照深度方向搜索,它类似于树的先根遍历,是树的先根遍历的推广。 

    深度优先搜索图的基本思想是:

  假设图G初态为所有顶点未被访问(visited[i]=false),从G中任选一顶点vi :

 ⑴、从该顶点vi出发,首先访问vi,并置visited [vi ]=true;

 ⑵、然后依次搜索vi的每一个邻接点vj ;

 ⑶、若vj未被访问过,则以vj为新的初始出发点,重复⑴

    若vj已被访问过,则返回到vi另一个邻接点,重复⑶

 ⑷、如果经过⑴、⑵、⑶后,图中仍有未被访问的顶点,再从中任选一顶点,重复⑴、⑵、⑶,直至所有顶点都被访问过,遍历结束。

 

C/C++代码实现图(有向图)的深度,广度优先遍历_第1张图片C/C++代码实现图(有向图)的深度,广度优先遍历_第2张图片

<二>广度优先搜索遍历图(树的层次遍历的推广)

1. 从图中某顶点v出发,在访问v之后,

2. 依次访问v的各个未曾被访问过的邻接点,   

3. 然后分别从这些邻接点出发依次访问它们的邻接点,并使“先被访问的顶点的邻接点”先于“后被访问的顶点的邻接点”被访问,直至图中所有已经被访问的顶点的邻接点都被访问到;

4. 若图中尚有顶点未曾被访问,则另选图中一个未曾被访问的顶点作起始点,访问该顶点,继续过程2、3,直至图中所有顶点都被访问到为止。

   (1)为避免重复访问, 需要一个辅助数组 visited[ n],给被访问过的顶点加标记。

   (2)为了实现逐层(按顶点的路径长度递增)访问, 算法中需使用了一个队列,以记忆正在访问的这一层和下一层的顶点,以便于向下一层访问。

C/C++代码实现图(有向图)的深度,广度优先遍历_第3张图片

C/C++代码实现图(有向图)的深度,广度优先遍历_第4张图片
C/C++代码实现图(有向图)的深度,广度优先遍历_第5张图片C/C++代码实现图(有向图)的深度,广度优先遍历_第6张图片C/C++代码实现图(有向图)的深度,广度优先遍历_第7张图片

代码如下:


#include
#include
#define MAX_VERTEX_NUM 20
typedef int InfoType;
typedef int VertexType;
typedef enum{DG,DN,UDG,UDN}GraphKind;


# define MAXQSIZE 100
typedef int QElemType ;//队列
typedef struct//队列
{
 QElemType  *base;    // 动态分配存储空间
 int  front;                 // 头指针,指向队列头元素
 int  rear;                  // 尾指针,指向 队列尾元素的下一个位置
}SqQueue;


typedef struct  ArcNode//图
{
 int adjex;//该弧所指向的顶点的位置
 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;//图的当前顶点数和弧数
 GraphKind kind;//图的种类标志
}ALGraph;

int LocateVex(ALGraph G, int v)//确定v在G中位置,即顶点在G.vertices中的序号
{
 int i;
 for(i=0;i  {
  if (G.vertices[i].data==v) return i;
 }
 return -1;
  
}

// ###################生成图G的存储结构-邻接表###############################################
void CreateGraph(ALGraph &G)
{
 int k,sv,tv,i,j;

 cout<<"请输入图的顶点数(eg:5)";
 cin>>G.vexnum;
 cout<<"请输入图的弧数(eg:6)";
 cin>>G.arcnum;
// cout<<"请输入图的类型(eg:)";
// cin>>G.kind;// 输入顶点数、边数和图类:1

 for(k=0;k  {
  cout<<"请输入图的顶点信息";
  cin>>G.vertices[k].data;// 输入顶点
        G.vertices[k].firstarc=NULL;//初始化链表头指针为"空"
 }

 cout<<"请输入该图的弧(v1-->v2),例如:(v1=1,v2=3),(v1=2,v2=4)"<

 for(k=0;k  {
  cout<<"请输入第"<   cin>>sv;
  cout<<"请输入第"<   cin>>tv;// 输入一条边(弧)的始点和终点
  cout<

  i = LocateVex(G, sv);
  j = LocateVex(G, tv); // (比较)确定sv和tv在G中位置,即顶点在G.vertices中的序号
                                                               
  while((i<0||i>=G.vexnum)||(j<0||j>=G.vexnum)) //if (sv,tv) illegal,again
  { 
   cout<<"请输入第"<       cin>>sv;
      cout<<"请输入第"<       cin>>tv;
   cout<    i = LocateVex(G, sv);
   j = LocateVex(G, tv); // (比较)确定sv和tv在G中位置,即顶点在G.vertices中的序号
                                                           
  } //while end

  ArcNode *p;
  p=(ArcNode*)malloc(sizeof(ArcNode));
  if(!p)
  { 
   cout<<"Overflow!"; // 存储分配失败 
      return ;
  }
 
  p->adjex=j;// 对弧结点赋邻接点"位置“
  p->nextarc=G.vertices[i].firstarc;//头插法,将tv结点插入到第i个单链表中
  p->info=NULL;
  G.vertices[i].firstarc=p;// 插入链表G.vertices[i]
 }
}

//################有向表的深度优先遍历#####################################################################
void DFS(ALGraph G,int v,int visited[])
{
 int w;
 ArcNode *p;
 cout<";//访问第v+1个顶点;
 visited[v]=1;
 p=G.vertices[v].firstarc;
 if(p!=NULL)
 w=p->adjex;//w是v的下一个邻接点的位置,即第v+1个顶点的下一个顶点是第w+1个顶点;
 if (p!=NULL)//如果有邻接点w
 {
  if(visited[w]==0)//如果w没访问过
  {
   DFS(G,w,visited);
  }
  else//若访问过,则访问v的下一个邻接点,并返回至判断是否存在该邻接点
  {
   p=p->nextarc;//G.vertices[v].firstarc=G.vertices[v].firstarc->nextarc;
   if(p!=NULL) w=p->adjex;//w=G.vertices[v].firstarc->adjex;
  }
 }
}

void DFSTraverse(ALGraph G)
{
 
 int v,visted[MAX_VERTEX_NUM];
 for (v=0;v  {
  visted[v]=0;
 }
 for (v=0;v  {
  if(visted[v]==0)
   DFS(G,v,visted);
 }
 
}

 

//#############广度优先搜索遍历######################################################################
//~~~~~~~~~~~~辅助队列~~~~~~~~~~~~~~~~~~~~~~~~~
int InitQueue (SqQueue &Q)// 构造一个空队列Q
{
 Q.base=(QElemType*)malloc(MAXQSIZE*sizeof(QElemType));
 if(!Q.base)  
    {  
  cout<

  return 0;
    }
 
 Q.front=Q.rear=0;
    return 1;

int EnQueue(SqQueue &Q,QElemType e)// 插入元素e为Q的新的队尾元素
{
 if ((Q.rear+1)%MAXQSIZE==Q.front)//①判满
 {
  cout<<"Error ! The SqQeueu is full ! ";
  return 0;
 }
 Q.base[Q.rear]=e;// ②插入队尾
 Q.rear=(Q.rear+1)%MAXQSIZE;//③队尾指针后移
 return 1;
}

int DeQueue(SqQueue &Q,QElemType &e)// 若队列不空,则删除Q的队头元素,用e返回其值,并返回OK;  否则返回ERROR

{
 if (Q.rear==Q.front)
 {
  cout<   return 0;
 }
 e=Q.base[Q.front];
 Q.front=(Q.front+1)%MAXQSIZE;
 return(e);
}
int QueueEmpty(SqQueue Q) 
{
 if(Q.front==Q.rear)
  return (1);
 else
  return (0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void BFS(ALGraph G,int v,int visited[],SqQueue &Q)
{
 int u,w;
 
 ArcNode *p;
 cout<";//访问第v+1个顶点;
 visited[v]=1;
 EnQueue(Q,v);// v入队列
 while (!QueueEmpty(Q))
 {
  DeQueue(Q,u);// 队头元素出队并置为u
  p=G.vertices[v].firstarc;
  if(p!=NULL)
   w=p->adjex;
  for (;p!=NULL;)
  {
   if (visited[w]==0)
   {
    cout<";
    visited[w]=1;
    EnQueue(Q, w); // 访问的顶点w入队列
   }
   p=p->nextarc;
   if (p!=NULL)
    w=p->adjex;
  }
 }
}

void BFSTraverse(ALGraph G)
{
 SqQueue Q;
 int v,visted[MAX_VERTEX_NUM];
 for (v=0;v  {
  visted[v]=0;//初始化访问标志
 }
 InitQueue(Q);// 置空的辅助队列Q      
 for ( v=0;  v  {  
  if(visted[v]==0)// v 尚未访问
  BFS(G,v,visted,Q);// 调用BFS()
    }   
}

//###############main函数#################
void main()
{
 ALGraph G;
 CreateGraph(G);
 cout<<"深度优先遍历如下:"<  DFSTraverse(G);
 cout<<"End !"<  cout<  BFSTraverse(G);
 cout<<"End !"< }

你可能感兴趣的:(算法)