图的深度优先搜索

深度优先搜索(Depth First Search)遍历类似于树的先序遍历,是树的先序遍历的推广。
无向图的深度优先搜索算法的过程如下:
首先访问出发顶点v,然后选择一个与v相邻接且未被访问过的顶点w访问之,再从w出发开始进行深度优先搜索。
每当到达一个其所有相邻的邻接顶点都已被访问过的顶点,就从该顶点开始,依次退回到尚有邻接顶点未曾被访问过的顶点u,并从u开始进行深度优先搜索。
这个过程进行到所有顶点都被访问到为止,搜索过程结束。
如果无向图是连通的,搜索结束时就可以得到图中所有顶点的一个序列。

下面是用一个简单的4x4的邻接矩阵存储结构实现的无向无权图a

这里写图片描述

用邻接矩阵表示为:
这里写图片描述

存储结构代码表示为

typedef struct
{
    VertexType vexs[MaxVertexNum];                     //顶点表
    EdgeType edges[MaxVertexNum][MaxVertexNum];        //邻接矩阵,即边表
    int n,e;                                           //顶点数和边数 
}Mgraph;

深度优先搜索可描述为(虚线表示访问顺序)

这里写图片描述

具体实现的C语言代码如下:

#include<stdio.h>
#define MaxVertexNum 100
typedef char VertexType;
typedef int EdgeType;
typedef struct
{
    VertexType vexs[MaxVertexNum];                     //顶点表
    EdgeType edges[MaxVertexNum][MaxVertexNum];        //邻接矩阵,即边表
    int n,e;                                           //顶点数和边数 
}Mgraph;

bool visited[MaxVertexNum];                         //定义是否被访问数组  

void CreateMgraph(Mgraph *G)
{//建立有向无权图G的邻接矩阵存储 
    printf("请输入顶点数和边数\n");
    scanf("%d %d",&(G->n),&(G->e));
    int i,j;
    printf("请输入 %d 个顶点信息:\n",G->n);
    for(i=0; i<G->n; i++)
    {
        scanf("\n%c",&(G->vexs[i]));
    }
    for(i=0; i<G->n; i++)
       for(j=0; j<G->n; j++) 
        G->edges[i][j] = 0;                       //初始化邻接矩阵 
    printf("请输入每条边所对应的两顶点的序号\n");
    for(int k=0;k<G->e; k++)
    {
        scanf("\n%d,%d",&i,&j);
        G->edges[i][j] = 1;                  //若加入G->edges[j][i],则为无向图的邻接存储建立 
    } 
}

void DFS(Mgraph *G,int i)
{   
    int j;
    visited[i] = true;
    printf("%c ",G->vexs[i]);               //输出结点 
    for(j=0; j<G->n; j++)
     if(G->edges[i][j]==1 && !visited[j])           
      DFS(G,j);                           //对要访问的领接顶点进行递归调用 
}

void DFSTraverse(Mgraph *G)
{
    int i;
    for(i=0; i<G->n; i++)
     visited[i] = false;                 //初始化默认顶点都未被访问 
    for(i=0; i<G->n; i++)
     if(!visited[i]) 
      DFS(G,i);                         
} 

int main()
{
    Mgraph G;
    CreateMgraph(&G);
    printf("深度优先遍历结果为:"); 
    DFSTraverse(&G);
    printf("\n"); 
    return 0;
}

运行结果如下:

这里写图片描述

下面是邻接表实现,图示如下

这里写图片描述

深度优先搜索的顺序与前面相同,实现如下代码:

#include<stdio.h>
#include<stdlib.h>
#define maxsize 20
typedef char VertexType;
typedef struct node        //邻接表结点结构 
{
    int vertex;
    struct node *next;
}GLNode;

typedef struct              //顶点数组结构 
{
    VertexType vexs;
    GLNode *firstedge;
}VNode,Vex[maxsize];

typedef struct{    
    Vex vertices;           //邻接表
    int n,e;                //顶点数和边数 
}ALGraph;

bool visited[maxsize];      //定义是否被访问数组 

void InitGraph(ALGraph &G)
{//初始化邻接表 
    printf("请输入顶点个数和边数:\n");
    scanf("%d,%d",&(G.n),&(G.e));
    int i;
    printf("建立顶点表"); 
    for(i=0;i<G.n;i++)
      {  
        fflush(stdin);  
        G.vertices[i].vexs = getchar();                   //建立顶点表 
        G.vertices[i].firstedge = NULL;           
      }                 
}

void AddNode(ALGraph &G)  
{//建立边表 
    GLNode *s;
    int i,j,k;
    for(k=0;k<G.e;k++)
    { 
      fflush(stdin);  

      printf("读入(vi-vj)的顶点对序号\n");         //新建邻接结点 
      scanf("%d,%d",&i,&j);  
      s = (GLNode*)malloc(sizeof(GLNode));
      s->vertex = j;
      s->next = NULL;

      if(!G.vertices[i].firstedge)
        G.vertices[i].firstedge = s;               //接在表头  
      else
      {
        GLNode *p = G.vertices[i].firstedge;
        while(p->next)
            p = p->next;
        p->next = s; 
      }  
    }
}
void Dfs(ALGraph &G,int i)
{
    int j;
    printf("%c ",G.vertices[i].vexs);
    visited[i] = true;
    GLNode *p = G.vertices[i].firstedge;
    while(p)
    {
        if(!visited[p->vertex])
         Dfs(G,p->vertex);                     //对要访问的领接顶点进行递归调用 
        p = p->next;
    }
}
void Dfstraverse(ALGraph &G)
{
    int i;
    for(i=0;i<G.n;i++)
     visited[i] = false;                      //初始化都未曾访问过 

    for(i=0; i<G.n; i++)
     if(!visited[i])
     Dfs(G,i);
}
int main()
{
    ALGraph G;
    InitGraph(G);
    AddNode(G);
    Dfstraverse(G);
    return 0; 
} 

运行结果:

这里写图片描述

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
2. 系统设计 1.用到的抽象数据类型的定义 的抽象数据类型定义: ADT Graph{ 数据对象V:V是具有相同特性的数据元素的集合,称为顶点集 数据关系R: R={VR} VR={<v,w>|v,w∈V且P(v,w),<v,w>表示从v到w的弧, 谓词P(v,w)定义了弧<v,w>的意义或信息} 基本操作P: CreatGraph(&G,V,VR) 初始条件:V是的顶点集,VR是中弧的集合 操作结果:按V和VR的定义构造G DestroyGraph(&G) 初始条件:G存在 操作结果:销毁G InsertVex(&G,v) 初始条件:G存在,v和中顶点有相同特征 操作结果:在G中增添新顶点v …… InsertArc(&G,v,w) 初始条件:G存在,v和w是G中两个顶点 操作结果:在G中增添弧<v,w>,若G是无向的则还增添对称弧<w,v> …… DFSTraverse(G,Visit()) 初始条件:G存在,Visit是顶点的应用函数 操作结果:对进行深度优先遍历,在遍历过程中对每个顶点调用函数Visit一次且仅一次。一旦Visit()失败,则操作失败 BFSTraverse(G,Visit()) 初始条件:G存在,Visit是顶点的应用函数 操作结果:对进行广度优先遍历,在遍历过程中对每个顶点调用函数Visit一次且仅一次。一旦Visit()失败,则操作失败 }ADT Graph 栈的抽象数据类型定义: ADT Stack{ 数据对象:D={ai|ai∈ElemSet,i=1,2,…,n,n≥0} 数据关系:R1={<ai-1,ai>|ai-1,ai∈D,i=2,…,n} 约定an端为栈顶,ai端为栈底 基本操作: InitStack(&S) 操作结果:构造一个空栈S DestroyStack(&S) 初始条件:栈S已存在 操作结果:将S清为空栈 StackEmpty(S) 初始条件:栈S已存在 操作结果:若栈S为空栈,则返回TRUE,否则FALSE …… Push(&S,e) 初始条件:栈S已存在 操作结果:插入元素e为新的栈顶元素 Pop(&S,&e) 初始条件:栈S已存在且非空 操作结果:删除S的栈顶元素,并用e返回其值 StackTraverse(S,visit()) 初始条件:栈S已存在且非空 操作结果:从栈底到栈顶依次对S的每个数据元素调用函数visit(),一旦visit()失败,则操作失效 }ADT Stack 队列的抽象数据类型定义: ADT Queue{ 数据对象:D={ai|ai∈ElemSet,i=1,2,…,n,n≥0} 数据关系:Rl={<ai-1,ai>|ai-1,ai∈D,i=2,…,n} 约定其中ai端为队列头,an端为队列尾。 基本操作: InitQueue(&Q) 操作结果:构造一个空队列Q DestroyQueue(&Q) 初始条件:队列Q已存在 操作结果:队列Q被销毁,不再存在 QueueEmpty(Q) 初始条件:队列Q已存在 操作结果:若Q为空队列,则返回TRUE,否则FALSE …… EnQueue(&Q,e) 初始条件:队列Q已存在 操作结果:插入元素e为Q的新的队尾元素 DeQueue(&Q,&e) 初始条件:Q为非空队列 操作结果:删除Q的队头元素,并用e返回其值 }ADT Queue 2.主程序的流程: 调用CreateDN函数创建邻接表G; 调用PrintDN函数输出邻接表G; 调用DFSTraverse函数深度优先遍历; 调用BFSTraverse函数广度优先遍历
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值