图是一种多对多的关系,可以有零个或多个直接前驱,也可以有零个或多个直接后驱。相较于线性表和树,图的结点可以是任意的,而线性表有头结点,只要知道了头结点,那么整个线性表就可以直接访问,树有根结点,可以根据树的根结点直接访问整棵树的所有结点,也就是说线性表和树如果要访问的话只有从头部进入访问。而图就不一样了,可以选择任意的结点进行访问。所以在遍历图的时候就一定会有多个遍历方式。

图的创建

在创建图的时候我们一般采用二维数组的形式。根据bool矩阵来进行存储图的关系。行和列都代表结点

typedef struct Graph
{int **connections;//创建一个二维数组int numNodes;//记录结点个数,从0开始编号如果有五个结点编号 0 1 2 3 4
} * GraphPtr;//初始化图
GraphPtr initGraph(int paraSize, int **paraData)
{int i, j;GraphPtr resultPtr = (GraphPtr)malloc(sizeof(Graph));//申请图的空间resultPtr->numNodes = paraSize;// resultPtr -> connections = (int**)malloc(paraSize * paraSize * sizeof(int));//申请二维数组空间resultPtr->connections = (int **)malloc(paraSize * sizeof(int *));for (i = 0; i < paraSize; i++){resultPtr->connections[i] = (int *)malloc(paraSize * sizeof(int));for (j = 0; j < paraSize; j++){resultPtr->connections[i][j] = paraData[i][j];//将图结点以0 1矩阵的方式存储} }      return resultPtr;
} 

在这里声明一下visitedPtr数组用来记录每一个结点是否被访问,下标代表结点,如果没有被访问数组值为0被访问数组值为1。

深度优先遍历

函数传入的参数是图和首先访问的结点,首先访问传入的结点,一旦访问就标记为1,然后从0 1 矩阵的该结点的行从左到右依次遍历,如果找到矩阵数为1,并且该列数没有被标记为1,那么就直接访问该结点。这里用到了递归的调用,在递归里面有for循环所以在递归到最后for循环截止的时候,就会返回上一个for循环继续向后递归,这里非常向N皇后问题,就不多做阐述。

void depthFirstTranverse(GraphPtr paraGraphPtr, int paraNode)
{int i;visitedPtr[paraNode] = 1;//如果结点被访问就标记为1,之后不再访问该结点printf("%d\t", paraNode);//打印出遍历的结点for (i = 0; i < paraGraphPtr->numNodes; i++){if (!visitedPtr[i]){if (paraGraphPtr->connections[paraNode][i]){//如果该结点connection[paraNode][i](结点编号为i)与paraNode结点相连,那么就打印,再次递归调用该函数、depthFirstTranverse(paraGraphPtr, i);} }    }
} 

广度优先遍历

广度优先遍历用到了队列,该函数传入的参数是图,首先遍历的结点。还是像深度优先遍历一样如果结点被访问标记为1,没有被访问标记为0。首先进行打印遍历,然后再将该结点入队,同深度优先遍历一样,如果结点的行有矩阵数为1并且该列列数没有被标记为1那么就直接打印遍历。

void widthFirstTranverse(GraphPtr paraGraphPtr, int paraStart)
{int i, j, tempNode;i = 0;QueuePtr tempQueuePtr = initQueue();//队列创建并初始化printf("%d\t", paraStart);//打印结点visitedPtr[paraStart] = 1;//标记结点enqueue(tempQueuePtr, paraStart);//入队while (!isQueueEmpty(tempQueuePtr)){tempNode = dequeue(tempQueuePtr);visitedPtr[tempNode] = 1;// For output.i++;for (j = 0; j < paraGraphPtr->numNodes; j++){if (visitedPtr[j])continue;if (paraGraphPtr->connections[tempNode][j] == 0)continue;printf("%d\t", j);visitedPtr[j] = 1;enqueue(tempQueuePtr, j);} }
} 

所有代码

#include <stdio.h>
#include <malloc.h>#define QUEUE_SIZE 10int *visitedPtr;typedef struct GraphNodeQueue
{int *nodes;int front;int rear;
} GraphNodeQueue, *QueuePtr;QueuePtr initQueue()
{QueuePtr resultQueuePtr = (QueuePtr)malloc(sizeof(struct GraphNodeQueue));resultQueuePtr->nodes = (int *)malloc(QUEUE_SIZE * sizeof(int));resultQueuePtr->front = 0;resultQueuePtr->rear = 1;return resultQueuePtr;
}bool isQueueEmpty(QueuePtr paraQueuePtr)
{if ((paraQueuePtr->front + 1) % QUEUE_SIZE == paraQueuePtr->rear){return true;}return false;
} void enqueue(QueuePtr paraQueuePtr, int paraNode)
{// printf("front = %d, rear = %d.\r\n", paraQueuePtr->front, paraQueuePtr->rear);if ((paraQueuePtr->rear + 1) % QUEUE_SIZE == paraQueuePtr->front % QUEUE_SIZE){printf("Error, trying to enqueue %d. queue full.\r\n", paraNode);return;} paraQueuePtr->nodes[paraQueuePtr->rear] = paraNode;paraQueuePtr->rear = (paraQueuePtr->rear + 1) % QUEUE_SIZE;// printf("enqueue %d ends.\r\n", paraNode);
} int dequeue(QueuePtr paraQueuePtr)
{if (isQueueEmpty(paraQueuePtr)){printf("Error, empty queue\r\n");return NULL;} paraQueuePtr->front = (paraQueuePtr->front + 1) % QUEUE_SIZE;// printf("dequeue %d ends.\r\n", paraQueuePtr->nodes[paraQueuePtr->front]);return paraQueuePtr->nodes[paraQueuePtr->front];
} typedef struct Graph
{int **connections;int numNodes;
} * GraphPtr;GraphPtr initGraph(int paraSize, int **paraData)
{int i, j;GraphPtr resultPtr = (GraphPtr)malloc(sizeof(Graph));resultPtr->numNodes = paraSize;// resultPtr -> connections = (int**)malloc(paraSize * paraSize * sizeof(int));resultPtr->connections = (int **)malloc(paraSize * sizeof(int *));for (i = 0; i < paraSize; i++){resultPtr->connections[i] = (int *)malloc(paraSize * sizeof(int));for (j = 0; j < paraSize; j++){resultPtr->connections[i][j] = paraData[i][j];} }     return resultPtr;
} void initTranverse(GraphPtr paraGraphPtr)
{int i;visitedPtr = (int *)malloc(paraGraphPtr->numNodes * sizeof(int));for (i = 0; i < paraGraphPtr->numNodes; i++){visitedPtr[i] = 0;}
}void depthFirstTranverse(GraphPtr paraGraphPtr, int paraNode)
{int i;visitedPtr[paraNode] = 1;printf("%d\t", paraNode);for (i = 0; i < paraGraphPtr->numNodes; i++){if (!visitedPtr[i]){if (paraGraphPtr->connections[paraNode][i]){depthFirstTranverse(paraGraphPtr, i);} }     }
} void widthFirstTranverse(GraphPtr paraGraphPtr, int paraStart)
{int i, j, tempNode;i = 0;QueuePtr tempQueuePtr = initQueue();printf("%d\t", paraStart);visitedPtr[paraStart] = 1;enqueue(tempQueuePtr, paraStart);while (!isQueueEmpty(tempQueuePtr)){tempNode = dequeue(tempQueuePtr);visitedPtr[tempNode] = 1;// For output.i++;for (j = 0; j < paraGraphPtr->numNodes; j++){if (visitedPtr[j])continue;if (paraGraphPtr->connections[tempNode][j] == 0)continue;printf("%d\t", j);visitedPtr[j] = 1;enqueue(tempQueuePtr, j);} }
} void testGraphTranverse()
{int i, j;int myGraph[5][5] = {{0, 1, 0, 1, 0},{1, 0, 1, 0, 1},{0, 1, 0, 1, 1},{1, 0, 1, 0, 0},{0, 1, 1, 0, 0}};int **tempPtr;printf("Preparing data\r\n");tempPtr = (int **)malloc(5 * sizeof(int *));for (i = 0; i < 5; i++){tempPtr[i] = (int *)malloc(5 * sizeof(int));} for (i = 0; i < 5; i++){for (j = 0; j < 5; j++){// printf("i = %d, j = %d, ", i, j);// printf("%d\r\n", tempPtr[i][j]);tempPtr[i][j] = myGraph[i][j];// printf("i = %d, j = %d, %d\r\n", i, j, tempPtr[i][j]);} }      printf("Data ready\r\n");GraphPtr tempGraphPtr = initGraph(5, tempPtr);printf("num nodes = %d \r\n", tempGraphPtr->numNodes);printf("Graph initialized\r\n");printf("Depth first visit:\r\n");initTranverse(tempGraphPtr);depthFirstTranverse(tempGraphPtr, 4);printf("\r\nWidth first visit:\r\n");initTranverse(tempGraphPtr);widthFirstTranverse(tempGraphPtr, 4);
} int main()
{testGraphTranverse();return 1;
} 

运行结果

Preparing data
Data ready
num nodes = 5
Graph initialized
Depth first visit:
4       1       0       3       2
Width first visit:
4       1       2       0       3
PS D:\Data Struction\weekSix\student>

C语言数据结构_图、图的深度优先遍历、广度优先遍历相关推荐

  1. c++ 数据结构 图的应用(实现图的深度优先和广度优先遍历)——以邻接表为存储结构

    数据结构实习--图及应用(图的遍历) 一.问题描述 很多涉及图上操作的算法都是以图的遍历操作为基础的.试写一个程序,演示无向图的遍历操作. 二.基本要求 以邻接表为存储结构,实现连通无向图的深度优先和 ...

  2. 图的理解:深度优先和广度优先遍历及其 Java 实现

    遍历 图的遍历,所谓遍历,即是对结点的访问.一个图有那么多个结点,如何遍历这些结点,需要特定策略,一般有两种访问策略: 深度优先遍历 广度优先遍历 深度优先 深度优先遍历,从初始访问结点出发,我们知道 ...

  3. 【图】深度优先遍历 广度优先遍历

    文章目录 一.广度优先遍历 二.深度优先遍历 深度优先遍历和广度优先遍历是遍历图的两种常见方式,接下来就通过这两种方式来实现一下图具体遍历的过程 当我位于游乐园的景区 A 时,为了玩遍所有的景区我们有 ...

  4. P202 例9-2 以如图9-8所示的带权有向图为例,编写测试上述图的深度优先和广度优先遍历函数的程序。

    P202 例9-2 以如图9-8所示的带权有向图为例,编写测试上述图的深度优先和广度优先遍历函数的程序. 头文件1:SeqList.h #include<stdio.h>#define M ...

  5. 树的基本概念和遍历规则 数据结构和算法 二叉树遍历(前序、中序、后序、层次、深度优先、广度优先遍历)

    zsychanpin 博客园 首页 新随笔 联系 订阅 管理 树的基本概念和遍历规则 树的递归定义 树是n(n>0)个结点的有限集,这个集合满足下面条件:       ⑴有且仅有一个结点没有前驱 ...

  6. 【树】二叉树遍历算法(深度优先、广度优先遍历,前序、中序、后序、层次)及Java实现...

    [树]二叉树遍历算法(深度优先.广度优先遍历,前序.中序.后序.层次)及Java实现 目录 一.前序遍历 二.中序遍历 三.后序遍历 四.层次遍历 遍历的作用 二叉树是一种非常重要的数据结构,很多其它 ...

  7. c++ 遍历所有点且距离最短_编程小白暑期进阶笔记41-C语言数据结构与算法图遍历的应用...

    基于广度优先遍历算法的应用 思考题: (思考题答案: BFS(广度优先遍历)在一般的带权图中是不能解决最短路问题,了解BFS的都知道,BFS是根据节点到源节点之间的节点数遍历的,也就是先访问离源节点节 ...

  8. 图数据结构,以及使用递归方式实现图的深度优先和广度优先遍历

    源码概览 1.GraphDemo,用于演示一个图结构以及图的遍历. 2.Graph,表示图数据结构,维护顶点的集合与边的集合,并提供广度优先遍历和深度优先遍历方法. 3.Edge<V>,表 ...

  9. C语言数据结构与算法---图的遍历

    文章目录 一. 深度优先搜索(DFS) 1.概念及实现原理 2. 深度优先遍历的实现代码 1. 若图为邻接矩阵 2. 若图为邻接表 二. 广度优先搜索(BFS) 1. 概念及实现原理 2. 广度优先遍 ...

最新文章

  1. CSS书写技巧(转)
  2. [LeetCode] 303. Range Sum Query - Immutable
  3. Linux下CMake简明教程(八) 添加编译选项
  4. python pyusb库使用教程【在window10系统上操作USB】(操作Intel Realsense D435)
  5. 队列的其本应用_迷官问题
  6. 关于JS的传递方式的小理解
  7. Win10 连接 Ubuntu16.04.3(通过Xdrp连接xfce4界面)
  8. JavaWeb三大组件(ServletFilterListener)
  9. Ble扫描导致wifi信号弱/断开解决
  10. 为什么有那么多人选择Python,真的有那么好吗?
  11. 20145239杜文超 《Java程序设计》第3周学习总结
  12. 关于VGGNet网络结构浅谈(主要是VGG16结构)
  13. 【LKJ】LKJ2000型记录装置显示界面说明
  14. 【硬件】PIC32单片机烧写器以及线序说明
  15. cad缩放_CAD常见问题详解,解决你当前的烦恼
  16. 台式计算机设置热点,台式电脑怎样设置wifi热点?设置wifi热点流程一览
  17. 观《蓝天铁翼-红旗军演》所想到的
  18. Swoole进阶——02 内存之Table
  19. 基于JAVA SSM框架的学校家长互动学习平台
  20. virtual Box与Vagrant的安装与踩坑

热门文章

  1. 怎样正确选择电动机的功率?
  2. Ubuntu16.04没有wifi链接的问题
  3. [大数据技术与应用省赛学习记录二]——模块一(HADOOP完全分布式集群搭建)
  4. PowerDesigner 数据模型导入导出 Excel
  5. linux查看子网掩码命令,Linux查看网关、子网掩码、IP、广播地址
  6. 系统大全Ghost XP Sp3 2012 万圣节装机版v11.0
  7. Let your script window keep openning.
  8. 酸了,大厂程序员凡尔赛的一天…
  9. phonton的配置
  10. nux将redis的redis.conf中的daemonize配置为yes但还是前台启动