图的初识·遍历
创始人
2024-03-14 16:23:32

文章目录

  • 深度优先搜索[DFS]
    • 实现代码
  • 广度优先搜索【BFS】
    • 思路图解
    • 代码实现·广度优先遍历【BFS】
      • 图的结构

深度优先搜索[DFS]

  • 并不唯一,只是一种情况A−>IA->IA−>I
    在这里插入图片描述

实现代码

在这里插入图片描述

  • 使用邻接表表示图。遍历的时间复杂度O(V+E)O(V+E)O(V+E);邻接矩阵的时间复杂度为O(V2)O(V^2)O(V2)
#include 
#include 
#define MaxVertex 5
typedef char E;
//结点和头节点分开定义,普通结点记录邻接顶点信息
typedef struct node {int nextVertex;struct node *next;
} *Node;
//头节点记录元素
struct HeadNode {E element;struct node * next;
};typedef struct AdjacencyGraph {int vertexCount;//顶点数int edgeCount;//边数struct HeadNode vertex[MaxVertex];
}* Graph;
//初始化
Graph create();
//添加顶点
void addVertex(Graph graph,E element);
//添加边的关系
void addEdge(Graph graph,int a,int b);
//打印邻接表
void printGraph(Graph graph);
//深度优先搜索算法
int dfs(Graph graph,int startVertex,int targetVertex,int* visited);
#include "Map2.h"
//创建
Graph create() {Graph graph=(Graph) malloc(sizeof(struct AdjacencyGraph));graph->vertexCount=graph->edgeCount=0;return graph;
};
//添加顶点
void addVertex(Graph graph,E element) {if(graph->vertexCount>=MaxVertex) return;//添加新节点graph->vertex[graph->vertexCount].element=element;graph->vertex[graph->vertexCount].next=NULL;graph->vertexCount++;//顶点数更新
}
void addEdge(Graph graph,int a,int b) {//定义一个指向链表的头结点的下一结点指向Node node=graph->vertex[a].next;//开辟顶点空间Node newNode=(Node) malloc(sizeof(struct node));newNode->next=NULL;newNode->nextVertex=b;//如果头结点下面没有东西,就直接连接;否则,就遍历到最后一个结点后,添加新节点if(!node) {graph->vertex[a].next=newNode;//注意这里不能使用node,因为我们要真实地改变头节点的next指向}else {do{//如果已经连接到对应的结点,直接返回if(node->nextVertex==b) {free(newNode);newNode=NULL;return ;}//否则一直遍历到最后一个结点if(node->next) node=node->next;else break;//如果遭到了最后一个结点,直接结束}while(true);node->next=newNode;}graph->edgeCount++;//边数计数+1
}
//打印
void printGraph(Graph graph) {for(int i=0;ivertexCount;i++) {printf("%d | %c",i,graph->vertex[i].element);Node node=graph->vertex[i].next;while(node) {printf("-> %d",node->nextVertex);node=node->next;}printf("\n");}
}
/*** 深度优先搜索算法* @param graph 图* @param startVertex 起点顶点下标* @param targetVertex 目标顶点下标* @param visited 已到达过的顶点数组*/
int dfs(Graph graph,int startVertex,int targetVertex,int* visited) {visited[startVertex]=1;//标记访问过的结点//大一当前结点printf("%c->",graph->vertex[startVertex].element);//如果当前顶点就是要找的顶点,就直接返回if(startVertex==targetVertex) return 1;//遍历当前顶点所有的分支Node node=graph->vertex[startVertex].next;while(node) {//如果已经到过[做的其他分支、回头路],就停止if(!visited[node->nextVertex]) {//没到过就继续往下走//如果查找成功就返回一,不用再看其他分支。if(dfs(graph,node->nextVertex,targetVertex,visited)) {return 1;}}node=node->next;}return 0;//当下的遍历都结束后,还是没有找到就返回零
}
#include "Map2.h"int main() {Graph graph1 = create();for (int c = 'A'; c <= 'F'; c++) {addVertex(graph1, (char) c);}addEdge(graph1, 0, 1);//A->BaddEdge(graph1, 1, 2);//B->CaddEdge(graph1, 1, 3);//B->DaddEdge(graph1, 1, 4);//D->E//addEdge(graph1, 4, 5);//E->FprintGraph(graph1);int arr[graph1->vertexCount];for(int i=0;ivertexCount;i++) {arr[i]=0;}printf("\n%d",dfs(graph1,0,5,arr));return 0;
}

在这里插入图片描述

广度优先搜索【BFS】

  • 先探索顶点的所有分支,然后再去看这些分支的所有分支。
  • 实质上是更尽可能地探索更广的范围。

思路图解

从A结点开始探索,A入队列。队列状态:A然后,再将其下一个结点B入队,A出队。队列状态:B从A结点开始探索,A入队列。\\ 队列状态:A\\ 然后,再将其下一个结点B入队,A出队。\\ 队列状态:B\\ 从A结点开始探索,A入队列。队列状态:A然后,再将其下一个结点B入队,A出队。队列状态:B
在这里插入图片描述
将B的下一级结点入队队列状态:B−>H−>G−>K将B出队队列状态:H−>G−>K将B的下一级结点入队\\ 队列状态:B->H->G->K\\ 将B出队\\ 队列状态:H->G->K 将B的下一级结点入队队列状态:B−>H−>G−>K将B出队队列状态:H−>G−>K
在这里插入图片描述
依次按照队头到队尾的顺序,将其子节点入队,本结点出队。C入队队列状态:H−>G−>K−>CH出队对列状态:G−>K−>C依次按照队头到队尾的顺序,将其子节点入队,本结点出队。\\ C入队\\ 队列状态:H->G->K->C\\ H出队\\ 对列状态:G->K->C 依次按照队头到队尾的顺序,将其子节点入队,本结点出队。C入队队列状态:H−>G−>K−>CH出队对列状态:G−>K−>C
在这里插入图片描述
D、F入队;C已入队,所以无需再次入队。队列状态:G−>K−>C−>D−>FG出队对列状态:K−>C−>D−>FD、F入队;C已入队,所以无需再次入队。\\ 队列状态:G->K->C->D->F\\ G出队\\ 对列状态:K->C->D->F\\ D、F入队;C已入队,所以无需再次入队。队列状态:G−>K−>C−>D−>FG出队对列状态:K−>C−>D−>F
在这里插入图片描述
K没有下一个结点,所以直接将K出队。队列状态:C−>D−>FK没有下一个结点,所以直接将K出队。\\ 队列状态:C->D->F K没有下一个结点,所以直接将K出队。队列状态:C−>D−>F
在这里插入图片描述
再依次遍历队头的下一个结点E入队队列状态:C−>D−>F−>EC出队队列状态:D−>F−>E再依次遍历队头的下一个结点\\ E入队\\ 队列状态:C->D->F->E C出队\\ 队列状态:D->F->E 再依次遍历队头的下一个结点E入队队列状态:C−>D−>F−>EC出队队列状态:D−>F−>E
在这里插入图片描述
因为D、F没有下一级邻接点,所以将D、F出队即可队列状态:E因为D、F没有下一级邻接点,所以将D、F出队即可\\ 队列状态:E 因为D、F没有下一级邻接点,所以将D、F出队即可队列状态:E

在这里插入图片描述
I、J入队队列状态:E−>I−>JE出队队列状态:I−>JI、J入队\\ 队列状态:E->I->J E出队\\ 队列状态:I->J I、J入队队列状态:E−>I−>JE出队队列状态:I−>J
在这里插入图片描述
最后再将队列的内容全部出队队列状态:空结束搜索最后再将队列的内容全部出队\\ 队列状态:空\\ 结束搜索 最后再将队列的内容全部出队队列状态:空结束搜索

代码实现·广度优先遍历【BFS】

  • 存储结构:邻接表

图的结构

在这里插入图片描述

typedef int T;
struct QueueNode{T element;struct QueueNode * next;
};
typedef struct QueueNode* QNode;
struct Queue{QNode front,rear;
};
typedef struct Queue* LinkedQueue;
int initQueue(LinkedQueue queue) {QNode node=(QNode) malloc(sizeof(struct QueueNode));if(node==NULL) return 0;queue->front=queue->rear=node;return 1;
}int offerQueue(LinkedQueue queue,T element) {QNode node=(QNode) malloc(sizeof(struct QueueNode));if(node== NULL) return 0;node->element=element;queue->rear->next=node;queue->rear=node;return 1;
}
int isEmpty(LinkedQueue queue){return queue->front==queue->rear;
};
T pollQueue(LinkedQueue queue) {T e=queue->front->next->element;QNode node=queue->front->next;queue->front->next=queue->front->next->next;if(queue->rear==node) queue->rear=queue->front;free(node);return e;
}
  • BFS
/**** @param graph 图* @param startVertex 起点顶点下标* @param targetVertex 目标顶点下标* @param visited 已到达过的顶点数组* @param queue 辅助作用的队列* @return*/
int bfs(Graph graph,int startVertex,int targetVertex,int* visited,LinkedQueue queue) {offerQueue(queue,startVertex);//头节点入队visited[startVertex]=1;//立马已标记//当队列不为空时,进行操作while(!isEmpty(queue)) {int next= pollQueue(queue);//从队列中取出一个顶点打印printf("%c->",graph->vertex[next].element);Node node=graph->vertex[next].next;//下一个结点//当当前结点的下一个结点存在时,进行入队操作while(node) {//如果找到目标结点,返回trueif(node->nextVertex==targetVertex) return true;if(!visited[node->nextVertex]) {//!0==1未访问offerQueue(queue,node->nextVertex);//入队列visited[node->nextVertex]=1;//访问标记}node=node->next;//进行下一个结点}}return false;
}
  • Main.cpp
Graph graph1 = create();
for (int c = 'A'; c <= 'F'; c++) {addVertex(graph1, (char) c);
}
addEdge(graph1, 0, 1);//A->B
addEdge(graph1, 1, 2);//B->C
addEdge(graph1, 1, 3);//B->D
addEdge(graph1, 1, 4);//D->E
addEdge(graph1, 4, 5);//E->F
printGraph(graph1);
int arr1[graph1->vertexCount];
for(int i=0;ivertexCount;i++) {arr1[i]=0;
}
struct Queue queue;
initQueue(&queue);
bfs(graph1,0,5,arr1,&queue);

在这里插入图片描述

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...