1. 查找函数(LocateVex查找坐标)
  2. 构建无向图(Undirected Graph)
  3. 输出邻接矩阵(print)
  4. 深度优先查找函数(DFS)
  5. 深度优先遍历(DFSTraverse)

图的遍历

  1. 深度优先遍历(DFS):类似于树中的先序遍历,整体思想是:先输出当前结点,在根据一定的次序去递归查找孩子。
  2. 广度优先遍历(BFS):类似于树中的层次遍历,需要用队列来体现结点访问的次序关系。

图的遍历需要考虑的问题

  1. 图是一种多对多的关系,每一个顶点有若干个,结点之间也有若干条回路,每一个连通图都有若干种路径,那么我们怎么知道结点是否已经被访问过?
  • 设置 "标志"数组 visited,数组每一位都对应一个结点的访问状态,0代表未被访问,1代表已访问。并且visited数组要设置成全局变量
  1. 连通图与非连通图的问题
  • 如果是连通图,根据程序递归,以任意一个端点为起点都可以走完整个图
  • 如果是非连通图,存在“落单”的端点,“孤岛”端点,既无法一次走完整个图,此时就需要多次调用遍历函数来保证每一个结点都被访问到。
  • 回到算法设计上而言,也就是解释了为什么会出现DFS、DFSTraverse两个函数,其实,如果是连通图由DFS函数就可以完成对整个图的遍历,DFSTraverse里面的for(i=0;i<G->vexnum;i++)(邻接矩阵第134-139行,邻接表第150-155行)就是为了非连通图而准备的。
  • 由水流的例子,我们还可以知道:

深度优先遍历基本步骤

  1. 设置全局变量visited数组并初始化为全0,代表所有节点均未被访问
  2. 根据端点存放顺序:
  • 2.1 选取初始端点:对初始端点进行访问,并在visited数值中标记成已访问状态(代码演示的初始端点是G->Vertex[i],此时i=0)
  • 2.2 由初始端点开始对后续端点进行处理
    (步骤2为深度优先搜索
  1. 循环对所有节点都执行步骤2,前提是该节点未被访问!(对应函数DFSTraverse,主要用于非连通图能访问到每一个结点)
    (步骤3 循环执行深度优先搜索,就是深度优先遍历

完整源代码:

  1. 注:图的遍历算法在任何图与网中都适用,此处仅用无向图UDG进行演示!
  2. 注:邻接矩阵和邻接表对同一个图的深度优先遍历顺序是不一样的!因为此处邻接表的边关系是由头插法的形式插入,若采用尾插法则遍历序列与邻接矩阵一致

1.邻接矩阵的深度优先遍历

#include <stdio.h>
#include <stdlib.h>
#define VertexMax 100 //最大顶点数为100typedef char VertexType; //每个顶点数据类型为字符型 typedef struct
{VertexType Vertex[VertexMax];//存放顶点元素的一维数组 int AdjMatrix[VertexMax][VertexMax];//邻接矩阵二维数组 int vexnum,arcnum;//图的顶点数和边数
}MGraph;int LocateVex(MGraph *G,VertexType v)//查找元素v在一维数组 Vertex[] 中的下标,并返回下标
{int i;for(i=0;i<G->vexnum;i++){if(v==G->Vertex[i]){return i; } } printf("No Such Vertex!\n");return -1;
}//无向图
void CreateUDG(MGraph *G)
{int i,j;printf("输入顶点个数和边数:\n");printf("顶点数 n="); scanf("%d",&G->vexnum);printf("边  数 e="); scanf("%d",&G->arcnum);printf("\n"); printf("\n");printf("输入顶点元素(无需空格隔开):");scanf("%s",G->Vertex);printf("\n");for(i=0;i<G->vexnum;i++) for(j=0;j<G->vexnum;j++){G->AdjMatrix[i][j]=0;}int n,m;VertexType v1,v2;printf("请输入边的信息:\n");for(i=0;i<G->arcnum;i++){scanf(" %c%c",&v1,&v2);n=LocateVex(G,v1); m=LocateVex(G,v2); if(n==-1||m==-1){printf("NO This Vertex!\n");return;} G->AdjMatrix[n][m]=1;G->AdjMatrix[m][n]=1;} }void print(MGraph G)
{int i,j;printf("\n-------------------------------");printf("\n 邻接矩阵:\n\n");     printf("\t ");for(i=0;i<G.vexnum;i++)printf("  %c",G.Vertex[i]);printf("\n");for(i=0;i<G.vexnum;i++){printf("\t%c",G.Vertex[i]);for(j=0;j<G.vexnum;j++){printf("  %d",G.AdjMatrix[i][j]);}printf("\n");}
}/*深度优先遍历DFS*/
int visited[VertexMax];//定义"标志"数组为全局变量 void DFS(MGraph *G,int i)
{int j;//1.处理起始点 printf("%c",G->Vertex[i]);//1.输出起始结点 visited[i]=1;//2.将已访问的结点标志成1//2.由起始点开始,对后续结点进行操作for(j=0;j<G->vexnum;j++)//依次搜索vi的邻接点 {if(G->AdjMatrix[i][j]==1&&visited[j]==0)//当满足有边且未被访问过时,递归调用去查找该邻接点 {DFS(G,j);//注意此处的G已经是指针类型,不需要再&G }}}void DFSTraverse(MGraph *G)
{int i;//初始化"标志"数组为0,代表未访问for(i=0;i<G->vexnum;i++){visited[i]=0; } for(i=0;i<G->vexnum;i++){if(visited[i]==0){DFS(G,i);//注意此处的G已经是指着类型,不需要再&G }} }int main()
{MGraph G;CreateUDG(&G);print(G); printf("\n\n深度优先遍历:"); DFSTraverse(&G); return 0;
}   

2.邻接表的深度优先遍历:

#include <stdio.h>
#include <stdlib.h>
#define VertexType char //顶点的数据类型(char)
#define VertexMax 20 //最大顶点个数 typedef struct ArcNode//边表
{int adjvex;//存储的是该顶点在顶点数组即AdjList[]中的位置 struct ArcNode *next;
}ArcNode;typedef struct VNode //顶单个点
{VertexType vertex;struct ArcNode *firstarc;
}VNode;typedef struct //顶点表
{VNode AdjList[VertexMax];//由顶点构成的结构体数组 int vexnum,arcnum; //顶点数和边数
}ALGraph;int LocateVex(ALGraph *G,VertexType v)
{    int i;for(i=0;i<G->vexnum;i++){if(v==G->AdjList[i].vertex){return i;}}printf("No Such Vertex!\n");return -1;
}//2.无向图
void CreateUDG(ALGraph *G)
{int i,j;//1.输入顶点数和边数printf("输入顶点个数和边数:\n");printf("顶点数 n="); scanf("%d",&G->vexnum);printf("边  数 e="); scanf("%d",&G->arcnum);printf("\n"); printf("\n");//2.顶点表数据域填值初始化顶点表指针域printf("输入顶点元素(无需空格隔开):");for(i=0;i<G->vexnum;i++){scanf(" %c",&G->AdjList[i].vertex);G->AdjList[i].firstarc=NULL;} printf("\n");//3.输入边信息构造邻接表int n,m;VertexType v1,v2;ArcNode *p1,*p2; printf("请输入边的信息:\n\n"); for(i=0;i<G->arcnum;i++){   //输入边信息,并确定v1和v2在G中的位置,即顶点在AdjList[]数组中的位置(下标) printf("输入第%d条边信息:",i+1); scanf(" %c%c",&v1,&v2);n=LocateVex(G,v1);m=LocateVex(G,v2);if(n==-1||m==-1){printf("NO This Vertex!\n");return;} p1=(ArcNode *)malloc(sizeof(ArcNode));p1->adjvex=m;//填上坐标 p1->next=G->AdjList[n].firstarc;//改链(头插法) G->AdjList[n].firstarc=p1;p2=(ArcNode *)malloc(sizeof(ArcNode));//无向图的对称 p2->adjvex=n;p2->next=G->AdjList[m].firstarc;G->AdjList[m].firstarc=p2;}//for } void print(ALGraph G)
{int i;ArcNode *p;printf("\n-------------------------------");printf("\n图的邻接表表示:\n");for(i=0;i<G.vexnum;i++){printf("\n   AdjList[%d]%4c",i,G.AdjList[i].vertex);p=G.AdjList[i].firstarc;while(p!=NULL){printf("-->%d",p->adjvex);p=p->next;}} printf("\n");
} /*深度优先遍历*/
int visited[VertexMax]; //定义数组为全局变量 void DFS(ALGraph *G,int i)
{int j;struct ArcNode *p;int w;printf("%c",G->AdjList[i].vertex);//1.访问当前节点 visited[i]=1;//2.将当前节点标记成已访问结点p=G->AdjList[i].firstarc;while(p!=NULL){w=p->adjvex;//w是邻接点的坐标 if(visited[w]==0){DFS(G,w);}p=p->next;//查找完之后,将p向后推一位 }} void DFSTraverse(ALGraph *G)
{int i;//初始化"标志"数组for(i=0;i<G->vexnum;i++){visited[i]=0;} for(i=0;i<G->vexnum;i++){if(visited[i]==0){DFS(G,i);}}
}int main()
{ALGraph G;CreateUDG(&G);print(G);printf("\n\n深度优先遍历:"); DFSTraverse(&G);  return 0;
}

执行结果:

  • 邻接矩阵
  • 邻接表

C语言-深度优先遍历相关推荐

  1. 实验报告C语言实现图的深度遍历,图的深度优先遍历的C语言实现.pdf

    图的深度优先遍历的C语言实现.pdf 维普资讯 九 江 职 业 技 术 学 院 学 报 JournalofJiujiangVocational&TechnicalCollege 2004.2 ...

  2. java语言实现图的深度优先遍历

    java语言实现图的深度优先遍历: 图的存储采用的是邻接矩阵存储的方式,对下面的无向图进行遍历 代码如下: public class Deep {int count=0;public static v ...

  3. 超详细C语言版数据结构:图的深度优先遍历(推荐收藏)

    文章目录 一.邻接矩阵存储图的深度优先遍历过程分析 二.结果分析 三.C语言编程实现图的深度优先遍历 四.图的遍历及其应用 一.邻接矩阵存储图的深度优先遍历过程分析 对图1这样的无向图,要写成邻接矩阵 ...

  4. 图的深度优先遍历和宽度优先遍历C语言,图的广度、深度优先遍历 C语言

    以下是老师作为数据结构课的作业的要求,没有什么实际用处和可以探讨和总结的的地方,所以简单代码直接展示. 宽度优先遍历: #include #include #include using namespa ...

  5. 二叉树的深度优先搜索c语言,C语言 二叉树按层打印、深度优先遍历、二叉树是否对称...

    #include//二叉树节点 typedef struct tree{ int data; struct tree *pLeft; struct tree *pRight; }Tree; //队列 ...

  6. 图的深度优先遍历和广度优先遍历_图的深度优先遍历(DFS)与广度优先遍历(BFS)的c语言实现...

    头文件 #pragma warning( disable : 4996)#pragma once#ifndef _GRAPH_H_#define _GRAPH_H_ #define MAX_VERTE ...

  7. 图的遍历(深度优先遍历DFS,广度优先遍历BFS)以及C语言的实现

    遍历的定义: 从已给的连通图中某一顶点出发,沿着一些边访遍图中所有的顶点,且使每个顶点仅被访问一次,就叫做图的遍历,它是图的基本运算. 一:深度优先遍历(DFS) 1,在访问图中某一起始顶点V后,由V ...

  8. 关于深度优先遍历算法-c++语言

    深度优先遍历及例题加讲解 竞赛里面重要算法,全当学习笔记啦.(如有不足多多谅解) 零.什么是深度优先遍历 深度优先遍历简称DFS(Depth First Search). 我们简单的举个栗子: 从前有 ...

  9. 数据结构—无向图创建邻接矩阵、深度优先遍历和广度优先遍历(C语言版)

    无向图创建邻接矩阵.深度优先遍历和广度优先遍历 一.概念解析: (1)无向图: (2)邻接矩阵: 二.创建邻接矩阵: 三.深度遍历.广度遍历 (1)深度遍历概念: (2)广度遍历概念: 四.实例展示 ...

最新文章

  1. 哪些人适合学习软件测试
  2. 如果你只做自己能力范围内的事,那么你永远没法进步
  3. captura录屏没声音_电脑录屏有哪些好用的软件呢?
  4. 二进制安全与MySQL的关系_《高可用MySQL》节选 -- 安全和二进制日志
  5. php源码仿三一重工,织梦仿三一重工业大学气企业网站php源码
  6. 网络安全系列之三十九 在Linux中配置访问控制列表ACL
  7. IOT(30)---庆科物联网平台架构分析
  8. MySQL数据库(七)
  9. 内存少导致编译出错,内存增加到24G
  10. python生成随机姓名
  11. 20年前的人机大战,IBM“深蓝”耍了花招
  12. mysql查询之左连接查询与右连接查询
  13. [RK3399][Android7.1.1]系统强制App横屏显示
  14. 高山大学2019级学员名单:但斌、王高飞、胡玮炜等入选
  15. STM32学习总结(二)
  16. 数据库——如何求出候选码
  17. dw01均衡电路_DW01内部原理图
  18. 搭讪技巧,希望所有单身的程序员兄弟都有女朋友哦!!
  19. 【每日早报】2019/12/31
  20. linux常用命令大全(linux基础命令入门到精通+实例讲解+持续更新+命令备忘录+面试复习)

热门文章

  1. 资深HR告诉你,面试中你不知道的那些秘密!
  2. 在 Apple 芯片设备上用 Android Studio?别忘了使用 Apple 芯片预览版!
  3. NoSQL 简单介绍
  4. 教你做一个可以自定义的电子生日礼物(放屁熊猫生日礼物+VBS)
  5. VTK学习-第一个多柱体生成
  6. python 如何计算平方、次方?平方根、方根?(math.pow()、math.sqrt())
  7. 介绍计算机配置的英语作文,用英语描述一个电脑的最新配置
  8. 北京大学2009年4月18日计算机会场QA
  9. 【PDN仿真笔记7-使用Sigrity PowerSI进行PDN仿真的方法2】
  10. python from __future__ import