目录

深度优先遍历(DFS)和广度优先遍历(BFS)原理

1、自己的原理图

2、官方原理图

一、邻接矩阵的深度优先遍历(DFS)

1、原理图

2、 过程:

3、总代码

二、邻接表的深度优先遍历(DFS):

1、原理图:

2、过程

3、总代码

三、邻接矩阵的广度优先遍历

1、原理图

2、过程

3、总代码

四、邻接表的广度优先遍历(BFS)

总代码


深度优先遍历(DFS)和广度优先遍历(BFS)原理

1、自己的原理图

2、官方原理图

DFS(深度优先遍历): 以一个顶点为根,逐顶点地往下遍历,遇到没遍历过的顶点则继续遍历;遇到遍历过的顶点则回溯。(递归实现)

BFS(广度优先遍历):以一个顶点为根,逐层地往下遍历,遇到遍历的顶点遍历;遍历过的顶点则忽略。(队列实现)

一、邻接矩阵的深度优先遍历(DFS)

1、原理图

2、 过程

1、矩阵形式的话,先从根开始走,遇到0就继续,遇到1直接跳到那一行(即跳到那一个元素),后面如此往复,用递归实现。

2、还有就是需要判断结点是否已经遍历过了,已经遍历过的结点不再进入,由于每一列都是同一结点(待遍历),可以通过一个判断数组记录每一个元素是否遍历。

//深度优先遍历
void DFS(int index)
{int i, j;for (i = index; i < G.vertexNum; i++){for (j = 0; j < G.vertexNum; j++){if (i == 0 && j == 0){printf("%c", G.vertex[j]);                            //输出首元素(根)Judge[j] = 1;                                            //标记首列}if (G.edge[i][j] != 0 && Judge[j] == 0)       //邻接矩阵有元素;且01数组无标记(即未被访问){printf("%c", G.vertex[j]);if (Judge[j] == 0)                                   //未标记Judge[j] = 1;                                 //对列做标记DFS(j);}}}
}

3、总代码

//图的深度优先遍历(邻接矩阵)
//需要创建一个列数组,按照矩阵的顺序遍历,为1就直接跳到那个结点
//增添一个数组,判断每个结点是否遍历过
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>#define MAXSIZE 20
int ColumnArray[MAXSIZE];       //列矩阵(判断有没有走过)//邻接矩阵
typedef struct
{char vertex[MAXSIZE];                  //顶点int edge[MAXSIZE][MAXSIZE];     //邻接顶点int vertexNum;                                //顶点数量
}Graph;
Graph G;//输入顶点
void InputVertex()
{int i = 0;char ch;printf("请输入需要创建的图顶点(不需要空格):\n");do{scanf("%c", &ch);if (ch != '\n')G.vertex[i++] = ch;} while (ch != '\n');G.vertexNum = i;
}//查找(根据结点找索引)
int findIndex(char ch)
{int i;for (i = 0; i < G.vertexNum; i++){if (G.vertex[i] == ch)return i;}return -1;             //没找到
}//创建图
void InputEdge()
{int i, index;char ch;for (i = 0; i < G.vertexNum; i++){printf("请输入%c指向的邻接结点:\n", G.vertex[i]);scanf("%c", &ch);while (ch != '\n'){index = findIndex(ch);          //查找输入结点的索引G.edge[i][index] = 1;scanf("%c", &ch);}}
}//01数组初始化
void InitColumnArray()
{int j;for (j = 0; j < G.vertexNum; j++)ColumnArray[j] = 0;                          //标记未访问
}//输出测试
void Print()
{int i, j;for (i = 0; i < G.vertexNum; i++){printf("\n%c结点的邻接结点为:\t", G.vertex[i]);for (j = 0; j < G.vertexNum; j++){if (G.edge[i][j] != 0)printf("%c\t", G.vertex[j]);}}
}//深度优先遍历
void DeepTraverse(int index)
{int i, j;for (i = index; i < G.vertexNum; i++){for (j = 0; j < G.vertexNum; j++){if (i == 0 && j == 0){printf("%c", G.vertex[j]);                                    //输出首元素(根)ColumnArray[j] = 1;                                          //标记首列}if (G.edge[i][j] != 0 && ColumnArray[j] == 0)     //邻接矩阵有元素;且01数组无标记(即未被访问){printf("%c", G.vertex[j]);if (ColumnArray[j] == 0)                                 //未标记ColumnArray[j] = 1;                                       //对列做标记DeepTraverse(j);}}}
}int main()
{//创建图InputVertex();InputEdge();InitColumnArray();printf("深度优先遍历结果:\n");//深度优先遍历DeepTraverse(0);//输出测试//Print();return 0;
}

二、邻接表的深度优先遍历(DFS):

1、原理图:

2、过程

和邻接矩阵类似,也是使用递归,也是需要用一个判断数组,表示每个顶点的邻接矩阵是否遍历过。只不过邻接表需要传一个参数lastIndex,利用这个参数把根结点输出出去。先把指针指向firstchild,后面利用一个while循环挨个判断邻接结点是否遍历过了,遍历过则指针继续后移;未遍历过则递归调用DFS函数进入那个未遍历的顶点,继续一个一个判断。

//深度优先遍历(按顶点操作)
//判断的时候需要遍历每一个邻接顶点,而输出的时候只需要把顶点数组的内容输出即可
void DFS(EdgeNode* p1, int lastIndex)
{if (Judge[lastIndex] == 0)       //顶点未遍历{Judge[lastIndex] = 1;      //标记(表示遍历过)printf("%c", V[lastIndex].data); //输出根顶点(保存lastIndex目的就是便于追溯到顶点数组,把根顶点输出)//开始遍历后面的邻接顶点while (p1 != NULL){if (Judge[p1->index] == 0)       //未遍历(遍历每一个顶点){DFS(V[p1->index].firstEdge, p1->index);      //递归深度优先遍历(输出只需要把顶点数组的东西输出即可)}p1 = *(p1->next);                               //后移(遍历每一个邻接顶点)}}
}

3、总代码

//邻接表的深度优先遍历(DFS)
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<malloc.h>#define MAXSIZE 20
int length = 0;                            //顶点数组长度
int Judge[MAXSIZE]; //列矩阵(记录顶点是否已遍历过)//邻接顶点
typedef struct EdgeNode
{char data;int index;struct EdgeNode** next;        //二级指针
}EdgeNode, * pEdgeNode;//顶点数组(结构体数组)
typedef struct Vertex
{char data;EdgeNode* firstEdge;
}Vertex;
Vertex V[MAXSIZE];void Input()
{int i;char ch;printf("请输入图的所有顶点:\n");scanf("%c", &ch);for (i = 0; i < MAXSIZE && ch != '\n'; i++){V[i].data = ch;scanf("%c", &ch);}length = i;
}void InitVertex()
{int i;for (i = 0; i < length; i++){V[i].firstEdge = NULL;Judge[i] = 0;             //列数组初始化}
}//根据字符查找在顶点数组中的下标
int FindIndex(char ch)
{int i;for (i = 0; i < length; i++){if (ch == V[i].data)return i;}return -1;                    //没找到
}//创建图
void CreateGraph()
{int i;char ch;pEdgeNode* p2 = NULL;               //二级指针for (i = 0; i < length; i++){printf("\n请输入%c的邻接顶点:\t", V[i].data);scanf("%c", &ch);//首个顶点if (ch != '\n'){V[i].firstEdge = (EdgeNode*)malloc(sizeof(EdgeNode));       //一级指针分配空间p2 = (pEdgeNode*)malloc(sizeof(pEdgeNode));                  //二级指针分配空间p2 = &V[i].firstEdge;(*p2)->data = ch;(*p2)->index = FindIndex(ch);(*p2)->next = (pEdgeNode*)malloc(sizeof(pEdgeNode));  //二级指针分配空间*((*p2)->next) = NULL;scanf("%c", &ch);}while (ch != '\n'){p2 = (*p2)->next;                                                                 //向后传递(*p2) = (EdgeNode*)malloc(sizeof(EdgeNode));                     //一级指针分配空间(*p2)->data = ch;(*p2)->index = FindIndex(ch);(*p2)->next = (pEdgeNode*)malloc(sizeof(pEdgeNode));        //二级指针分配空间*((*p2)->next) = NULL;scanf("%c", &ch);}}
}//深度优先遍历(按顶点操作)
//判断的时候需要遍历每一个邻接顶点,而输出的时候只需要把顶点数组的内容输出即可
void DFS(EdgeNode* p1, int lastIndex)
{if (Judge[lastIndex] == 0)       //顶点未遍历{Judge[lastIndex] = 1;      //标记(表示遍历过)printf("%c", V[lastIndex].data); //输出根顶点(保存lastIndex目的就是便于追溯到顶点数组,把根顶点输出)//开始遍历后面的邻接顶点while (p1 != NULL){if (Judge[p1->index] == 0)       //未遍历(遍历每一个顶点){DFS(V[p1->index].firstEdge, p1->index);      //递归深度优先遍历(输出只需要把顶点数组的东西输出即可)}p1 = *(p1->next);                               //后移(遍历每一个邻接顶点)}}
}//输出测试
void Print()
{int i;EdgeNode* p1;                    //一级指针for (i = 0; i < length; i++){p1 = V[i].firstEdge;while (p1 != NULL){printf("%c", p1->data);p1 = *(p1->next);}}
}int main(){Input();InitVertex();CreateGraph();                 //创建图DFS(V[0].firstEdge ,0);            //深度优先遍历(从首结点开始)//Print();
}

三、邻接矩阵的广度优先遍历

1、原理图

2、过程

先把根元素入队并标记,然后取出根元素,依次判断:1、当前根元素行邻接数组是否有元素;2、当前元素是否标记过 -> 若有元素且未标记,则入队该元素并标记;否则跳过。然后调用BFS()函数进行递归直到队列为空结束。(一个顶点一次循环判断入队

1、入队首元素并标记 ,调用BFS()

EnQueue(0);                              //首元素入队
Judge[0] = 1;                          //标记首元素
BFS(DeQueue());                         //广度优先遍历

2、 BFS()函数

//广度优先遍历(BFS)
void BFS(int index)
{int j;printf("%c", G.vertex[index]);     //输出for (j = 0; j < G.length; j++){if (G.edge[index][j] != 0 && Judge[j] == 0)         //有邻接顶点且未入队{Judge[j] = 1;                      //标记EnQueue(j);                         //入队}}//遍历队列下一个元素index = DeQueue();            //取出当前队首作为根//判断队列是否为空,空则退出,非空则继续遍历if (index == -1)return;elseBFS(index);                    //递归进行下一个元素的广度优先遍历
}

3、总代码

//邻接矩阵的广度优先遍历
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>#define MAXSIZE 20
int Judge[MAXSIZE] = { 0 };//队列结构体
typedef struct
{int rear;int front;int num[MAXSIZE];           //放入队列的序号
}Queue;
Queue Q;//邻接矩阵结构体
typedef struct
{char vertex[MAXSIZE];                      //顶点数组int edge[MAXSIZE][MAXSIZE];           //边数组int length;                                        //顶点数量
}Graph;
Graph G;//输入顶点
void Input()
{int i;char ch;printf("请输入全部顶点:\n");scanf("%c", &ch);for (i = 0; i < MAXSIZE && ch != '\n'; i++){G.vertex[i] = ch;scanf("%c", &ch);}G.length = i;                   //顶点数量
}//初始化(邻接结点数组和队列)
void Init()
{int i, j;for (i = 0; i < G.length; i++){for (j = 0; j < G.length; j++){G.edge[i][j] = 0;}}Q.rear = 0;            //队尾Q.front = 0;           //队首
}//入队
void EnQueue(int num)
{Q.num[Q.rear++] = num;
}//出队
int DeQueue()
{if (Q.front == Q.rear)return -1;return Q.num[Q.front++];
}//根据字符返回下标
int FindIndex(char ch)
{int i;for (i = 0; i < G.length; i++){if (G.vertex[i] == ch)return i;}return -1;                        //没找到
}//创建图
void CreateGraph()
{int i, index;char ch;for (i = 0; i < G.length; i++){printf("\n请输入%c结点的邻接结点:\t", G.vertex[i]);scanf("%c", &ch);while (ch != '\n'){index = FindIndex(ch);           //获取列下标(被指向元素下标)G.edge[i][index] = 1;scanf("%c", &ch);}}
}//广度优先遍历(BFS)
void BFS(int index)
{int j;printf("%c", G.vertex[index]);     //输出for (j = 0; j < G.length; j++){if (G.edge[index][j] != 0 && Judge[j] == 0)         //有邻接顶点且未入队{Judge[j] = 1;                      //标记EnQueue(j);                         //入队}}//遍历队列下一个元素index = DeQueue();            //取出当前队首作为根//判断队列是否为空,空则退出,非空则继续遍历if (index == -1)return;elseBFS(index);                    //递归进行下一个元素的广度优先遍历
}//测试遍历
void Print()
{int i, j;for (i = 0; i < G.length; i++){printf("\n%c邻接结点:\t", G.vertex[i]);for (j = 0; j < G.length; j++)printf("%d ", G.edge[i][j]);}
}int main()
{Input();Init();CreateGraph();EnQueue(0);                               //首元素入队Judge[0] = 1;                           //标记首元素printf("\n广度优先遍历:");BFS(DeQueue());                     //广度优先遍历//Print();return 0;
}

四、邻接表的广度优先遍历(BFS)

原理和上面的邻接矩阵类似,以顶点为单位,往后判断是否有需要入队的元素(只用判断是否遍历过即可,因为接在顶点后面作为邻接顶点,必然是邻接顶点,所以不需要再像数组那样判断是否为邻接顶点)。

1、首调用BFS

EnQueue(0);              //入队首元素
Judge[0] = 1;          //判断
BFS(DeQueue());         //广度优先遍历并出队队首元素

2、BFS()

//广度优先遍历
void BFS(int index)
{int i;EdgeNode* p;printf("%c", G[index].vertex);     //输出顶点p = G[index].firstEdge;                  //指向顶点首指针while (p){if (Judge[p->index] == 0){Judge[p->index] = 1;          //标记EnQueue(p->index);           //入队}p = *(p->next);                        //后移}if (Q.front == Q.rear)                   //队列为空return;elseBFS(DeQueue());                        //广度优先遍历并出队队首元素
}

总代码

//邻接表的广度优先遍历
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<malloc.h>#define MAXSIZE 20
int length;                         //记录顶点数组长度
int Judge[MAXSIZE] = { 0 };//邻接顶点结构体
typedef struct EdgeNode
{char data;                             //存放数据int index;                                //数据在顶点结构体中的下标struct EdgeNode** next;       //二级指针
}EdgeNode, *pEdgeNode;//顶点结构体
typedef struct
{char vertex;EdgeNode* firstEdge;           //一级指针(指向首个邻接顶点)
}Graph;
Graph G[MAXSIZE];//队列结构体
typedef struct
{int num[MAXSIZE];              //存放顶点下标int front;                              //队首int rear;                               //队尾
}Queue;
Queue Q;//输入顶点数组
void InputVertex()
{int i;char ch;printf("请输入所有顶点:\n");scanf("%c", &ch);for (i = 0; i < MAXSIZE && ch != '\n'; i++){G[i].vertex = ch;scanf("%c", &ch);}length = i;                 //顶点数组长度
}//初始化(*firstEdge和队列初始化)
void Init()
{int i;for (i = 0; i < length; i++){G[i].firstEdge = NULL;}Q.front = 0;         //队首Q.rear = 0;            //队尾
}//入队
void EnQueue(int num)
{Q.num[Q.rear++] = num;
}//出队
int DeQueue()
{return Q.num[Q.front++];
}//根据数据查找下标
int FindIndex(char ch)
{int i;for (i = 0; i < length; i++){if (ch == G[i].vertex)return i;}return -1;
}//创建邻接顶点链表
void CreateEdge()
{int i;char ch;pEdgeNode* p2=NULL;                 //二级指针for (i = 0; i < length; i++){printf("请输入%c顶点的邻接顶点:\t", G[i].vertex);scanf("%c", &ch);//首个顶点if (ch != '\n'){G[i].firstEdge = (EdgeNode*)malloc(sizeof(EdgeNode)); //一级指针p2 = (pEdgeNode*)malloc(sizeof(pEdgeNode));                  //二级指针p2 = &G[i].firstEdge;                                                            //连接首指针(*p2)->data = ch;                                                        (*p2)->index = FindIndex(ch);                                           (*p2)->next = (pEdgeNode*)malloc(sizeof(pEdgeNode));    //二级指针*((*p2)->next) = NULL;                                                        //尾指针地址赋空scanf("%c", &ch);}//后面的顶点while (ch != '\n'){p2 = (*p2)->next;(*p2)= (EdgeNode*)malloc(sizeof(EdgeNode));                     //一级指针 (*p2)->next = (pEdgeNode*)malloc(sizeof(pEdgeNode));     //二级指针(*p2)->data = ch;(*p2)->index = FindIndex(ch);*((*p2)->next) = NULL;scanf("%c", &ch);}}
}//广度优先遍历
void BFS(int index)
{int i;EdgeNode* p;printf("%c", G[index].vertex);     //输出顶点p = G[index].firstEdge;                  //指向顶点首指针while (p){if (Judge[p->index] == 0){Judge[p->index] = 1;          //标记EnQueue(p->index);           //入队}p = *(p->next);                        //后移}if (Q.front == Q.rear)                   //队列为空return;elseBFS(DeQueue());                        //广度优先遍历并出队队首元素
}//测试输出
void Print()
{int i; EdgeNode* p;for (i = 0; i < length; i++){p = G[i].firstEdge;printf("\n%c的邻接顶点为:\t", G[i].vertex);while (p != NULL){printf("%c", p->data);p = *(p->next);}}
}int main()
{InputVertex();         //输入顶点Init();                       //初始化CreateEdge();          //创建邻接顶点链表printf("\n广度优先遍历:\t");EnQueue(0);                //入队首元素Judge[0] = 1;           //判断BFS(DeQueue());     //广度优先遍历并出队队首元素//Print();                       //测试输出return 0;
}

才疏学浅,有些地方可能会有点错误的地方,还望大家斧正,Thanks♪(・ω・)ノ

数据结构与算法(7-2)图的遍历(深度优先遍历DFS、广度优先遍历BFS)(分别用邻接矩阵和邻接表实现)相关推荐

  1. Floyd(弗洛伊德)算法(邻接矩阵与邻接表实现)——暴力求解多源点最短路

    文章目录 Floyd(弗洛伊德)算法(邻接矩阵与邻接表实现)--暴力求解多源点最短路 简介 思想与原理 邻接矩阵解题模板 邻接表解题模板 Floyd(弗洛伊德)算法(邻接矩阵与邻接表实现)--暴力求解 ...

  2. 分别用邻接矩阵和邻接表实现图的深度优先遍历和广度优先遍历_数据结构与算法学习笔记:图...

    图: 图结构区别于线性结构和树型结构,区别可见下图 逻辑上的图(graph)结构由顶点(vertex)和边(edge)组成. 一个图结构G包含顶点集合V和边集合E,任何两个顶点之间可以有一个边表示两者 ...

  3. 分别用邻接矩阵和邻接表实现图的深度优先遍历和广度优先遍历_数据结构与算法:三十张图弄懂「图的两种遍历方式」...

    原创: 进击的HelloWorld1 引言遍历是指从某个节点出发,按照一定的的搜索路线,依次访问对数据结构中的全部节点,且每个节点仅访问一次. 在二叉树基础中,介绍了对于树的遍历.树的遍历是指从根节点 ...

  4. 分别用邻接矩阵和邻接表实现图的深度优先遍历和广度优先遍历_数据结构|图的邻接表与深度、广度优先搜索

    线性存储元素时,元素的关系也同时确定了.而非线性数据结构就不同了,需要同时考虑存储数据元素和数据元素的关系. 由于图的结构比较复杂,任意两个顶点之间都可能存在联系,因此无法以数据元素在存储区中的物理位 ...

  5. Java数据结构之图的基本概念和算法,深度优先遍历DFS,广度优先遍历BFS(图解)

    文章目录 前言 一.图的基本概念 1.图的定义 2.基本术语 二.图的基本算法 1.初始化图 2.插入顶点和边 3.矩阵打印 4.返回第一个邻接结点的下标 5.返回第一个邻接结点的下一个结点的下标 三 ...

  6. 数据结构与算法思维导图(学习笔记)

    版本 数据结构与算法思维导图V1.0 V1.0分享版本这个可以直接看,不需要下载. 说明 1.free 2.目前内容主要包含内容包含: 数据结构与算法思维导图 包含:线性表.顺序结构.链式结构,栈与队 ...

  7. 数据结构与算法学习笔记——图 C++实现

    数据结构与算法学习笔记--图 C++实现 1 概念 2 图的表示方法 3 算法 3.1 拓扑排序 3.2 图的搜索算法 3.2.1 广度优先搜索(BFS) 3.2.2 深度优先搜索(DFS) 3.3 ...

  8. 狄斯奎诺算法 c语言,图的邻接表实现迪杰斯特拉算法(C语言).doc

    图的邻接表实现迪杰斯特拉算法(C语言) /*迪杰斯特拉算法(狄斯奎诺算法)解决的是从源点到其它所有顶点的最短路径问题*/ //算法实现: #include #include #define MAX 2 ...

  9. 狄斯奎诺算法 c语言,图的邻接表实现迪杰斯特拉算法(C语言)

    图的邻接表实现迪杰斯特拉算法(C语言). 迪杰斯特拉算法(狄斯奎诺算法)解决的是从源点到其它所有顶点的最短路径问题. 图的邻接表实现迪杰斯特拉算法(C语言) /*迪杰斯特拉算法(狄斯奎诺算法)解决的是 ...

  10. 邻接表实现的有向带权图 及 图算法(C++)

    邻接表实现的有向带权图 相关概念 声明和定义 实现 1. 构造函数 2. 析构函数 3. 深度优先遍历 4. 广度优先遍历 5. 获取顶点在邻接表中对应的下标 6. 添加顶点 7. 移除顶点 8. 添 ...

最新文章

  1. 【原创】Cookie应用(二)
  2. Database design best practice(1):关于primary key及其它
  3. hibernate映射集合属性
  4. c语言双链表是什么意思,双链表的表示和实现(C语言)
  5. java字数统计,求大神教我,java语言里的字数统计功能的代码?
  6. 计算机操作系统实验银行家算法,实验六 银行家算法(下)
  7. html怎么显示数学公式,怎么使用html数学公式显示库MathJax - js笔记
  8. 转:Session,有没有必要使用它?
  9. Node.js 应该用在什么地方
  10. 微信小程序-Image 图片实现宽度100%,高度自适应
  11. 飞思卡尔c语言,飞思卡尔MCU的C语言编程框架
  12. python线程池如何使用
  13. 2019-05-15过了这么久我才写了这么点Hhhhhhhh今天也没有刷题我真的不是偷懒啊只是想赶紧弄完老师给的任务今天写的也很匆忙一会儿回去给姥姥姥爷打个电话然后买个晚餐回宿舍洗澡找妈妈视频啦啦啦了
  14. Android四大组件Service之AIDL详解
  15. 深度Linux安装火狐,Firefox
  16. python 老照片修复软件_这款开源的 Python 老照片修复工具火了
  17. 微信小程序实现微信登录以及获取用户手机号
  18. Elasticsearch 常见问题汇总及解决姿势(后续会持续更新)
  19. 新手如何在阿里云服务器上搭建自己的个人网站
  20. C语言程序设计Bjarne特别版,C语言程序设计(2013深色背景).ppt

热门文章

  1. ERROR: Manifest merger failed : uses-sdk:minSdkVersion 24 cannot be smaller than version 27 declared
  2. .svn提交项目提示更新副本
  3. AndroidManifest.xml
  4. [软件工程]技术规格说明书
  5. App Store兼容性问题
  6. 【洛谷P2024】食物链
  7. 运算符及题目(2017.1.8)
  8. 解决xcode ***is missing from working copy
  9. linux if 命令判断条件总结
  10. ASP.NET常用函数