图的深度遍历源代码

合集下载

图的深度广度优先遍历操作代码

图的深度广度优先遍历操作代码

一、实验目的1.掌握图的各种存储结构,特别要熟练掌握邻接矩阵和邻接表存储结构;2.遍历是图各种应用的算法的基础,要熟练掌握图的深度优先遍历和宽度优先遍历算法,复习栈和队列的应用;3.掌握图的各种应用的算法:图的连通性、连通分量和最小生成树、拓扑排序、关键路径。

二、实验内容实验内容1**图的遍历[问题描述]许多涉及图上操作的算法都是以图的遍历为基础的。

写一个程序,演示在连通无向图上遍历全部顶点。

[基本要求]建立图的邻接表的存储结构,实现无向图的深度优先遍历和广度优先遍历。

以用户指定的顶点为起点,分别输出每种遍历下的顶点访问序列。

[实现提示]设图的顶点不超过30个,每个顶点用一个编号表示(如果一个图有N个顶点,则它们的编号分别为1,2,…,N)。

通过输入图的全部边输入一个图,每条边是两个顶点编号对,可以对边依附顶点编号的输入顺序作出限制(例如从小到大)。

[编程思路]首先图的创建,采用邻接表建立,逆向插入到单链表中,特别注意无向是对称插入结点,且要把输入的字符在顶点数组中定位(LocateVex(Graph G,char *name),以便后来的遍历操作,深度遍历算法采用递归调用,其中最主要的是NextAdjVex(Graph G, int v, int w);FirstAdjVex ()函数的书写,依次递归下去,广度遍历用队列的辅助。

[程序代码]头文件:#include<stdio.h>#include<stdlib.h>#define MAX_VERTEX_NUM 30#define MAX_QUEUE_NUMBER 30#define OK 1#define ERROR 0#define INFEASIBLE -1#define OVERFLOW -2#define TRUE 1#define FALSE 0typedef int Status;typedef int InfoType;typedef int Status;/* 定义弧的结构*/typedef struct ArcNode{int adjvex; /*该边所指向的顶点的位置*/ struct ArcNode *nextarc; /*指向下一条边的指针*/ InfoType info; /*该弧相关信息的指针*/}ArcNode;/*定义顶点的结构*/typedef struct VNode{char data[40]; /*顶点信息*/ArcNode *firstarc; /*指向第一条依附该顶点的弧的指针*/}VNode,AdjList[MAX_VERTEX_NUM];/*定义图的结构*/typedef struct {AdjList vertices;int vexnum,arcnum; /*图的当前顶点数和弧数*/int kind; /*图的类型标志*/}Graph;/*定义队列的结构*/typedef struct{int *elem;int front, rear;}Queue;/*功能选择*/void MenuSelect(int w);/*顶点定位*/int LocateVex(Graph G,char *name);/*创建无向图*/void CreateGraph(Graph &G);/*求第一个顶点*/int FirstAdjVex(Graph G, int v);/*求下一个顶点*/int NextAdjVex(Graph G, int v, int w);/*深度递归*/void DFS(Graph G, int v) ;/*深度遍历*/void DFSTravel(Graph G,int v);/*广度遍历*/void BFSTraverse(Graph G,char *name);/*初始化队列*/Status InitQueue(Queue &Q);/*判空*/Status EmptyQueue(Queue Q);/*进队*/Status EnQueue(Queue &Q, int e);/*出队*/Status DeQueue(Queue &Q, int &e);实现文件:#include <stdio.h>#include"malloc.h"#include "tuhead.h"#include "stdlib.h"#include "string.h"bool visited[MAX_VERTEX_NUM];/************************************************************ 顶点定位************************************************************/int LocateVex(Graph G,char *name){int i;for(i=1;i<=G.vexnum;i++) //从1号位置开始存储if(strcmp(name,G.vertices[i].data)==0) //相等则找到,返回位序return i;return -1;}/************************************************************ 创建无向图************************************************************/void CreateGraph(Graph &G){ArcNode *p;char name1[10],name2[10];int i,j,k;printf(" 请输入顶点数,按回车键结束:");scanf("%d",&G.vexnum);printf(" 请输入弧数,按回车键结束:");scanf("%d",&G.arcnum);printf(" 请依次输入顶点名(用空格分开且字符小于10),按回车键结束:\n");printf(" ");for(i=1;i<=G.vexnum;i++) //从1号位置开始存储{scanf("%s",G.vertices[i].data); //从一号位置开始初始化G.vertices[i].firstarc=NULL;}printf("\n\n\n\n");printf(" ………………………………………输入小提示………………………………………\n");printf(" &&&&1 为避免输入遗漏,最好从选择任意一点,输入所有相邻边\n");printf(" &&&&2 输入边时格式(用空格分开,即格式为顶点(空格)顶点(空格))\n");printf(" ………………………………………输入小提示………………………………………\n\n\n\n");for(k=0;k<G.arcnum;k++){printf("请输入相邻的两个顶点,按回车键结束:");scanf("%s%s",name1,name2);i=LocateVex(G,name1); //返回位序j=LocateVex(G,name2);p=(ArcNode *)malloc(sizeof(ArcNode)); //申请边节点p->adjvex=j; //插入到邻接表中,注意此处为逆向插入到单链表中p->nextarc=G.vertices[i].firstarc;G.vertices[i].firstarc=p;//无向图,注意是对称插入结点p=(ArcNode *)malloc(sizeof(ArcNode));p->adjvex=i;p->nextarc=G.vertices[j].firstarc;G.vertices[j].firstarc=p;}}/************************************************************ 求第一个顶点************************************************************/int FirstAdjVex(Graph G, int v){ArcNode *p;if(v>=1 && v<=G.vexnum){p=G.vertices[v].firstarc;if(p->nextarc==NULL)return 0;elsereturn (p->nextarc->adjvex); //返回第一个顶点字符}return -1;}/************************************************************ 求下一个顶点************************************************************/int NextAdjVex(Graph G, int v, int w){ //在图G中寻找第v个顶点的相对于w的下一个邻接顶点ArcNode *p;if(v>=1 && v<=G.vexnum && w>=1 && w<=G.vexnum){p=G.vertices[v].firstarc;while(p->adjvex!=w)p=p->nextarc; //在顶点v的弧链中找到顶点wif(p->nextarc!=NULL)return 0; //若已是最后一个顶点,返回0 elsereturn(p->nextarc->adjvex); //返回下一个邻接顶点的序号}return -1;}/************************************************************ 深度递归************************************************************/void DFS(Graph G, int v){int w;ArcNode *p;visited[v]=1;printf("%s ",G.vertices[v].data); //访问第v个顶点p=G.vertices[v].firstarc; //p为依附顶点的第一条边while (p!=NULL){w=p->adjvex;if(visited[w]==0)DFS(G,w);p=p->nextarc; //下移指针}}/************************************************************ 深度遍历************************************************************/void DFSTravel(Graph G,int v){for(int i=1;i<=G.vexnum;i++)visited[i]=0;int w;ArcNode *p;visited[v]=1;printf("%s ",G.vertices[v].data); //访问第v个顶点p=G.vertices[v].firstarc;while (p!=NULL){w=p->adjvex;if(visited[w]==0)DFS(G,w);p=p->nextarc;}}/************************************************************ 初始化队列************************************************************/Status InitQueue(Queue &Q){Q.elem = new int[MAX_QUEUE_NUMBER];Q.front = Q.rear = 0;return OK;}Status EmptyQueue(Queue Q){if(Q.front==Q.rear)return 0;elsereturn 1;}/*********************************************************** * 进队列* ***********************************************************/ Status EnQueue(Queue &Q, int e){if((Q.rear + 1)%MAX_QUEUE_NUMBER != Q.front)Q.elem[Q.rear ] = e;else ;Q.rear = (Q.rear + 1)%MAX_QUEUE_NUMBER;return OK;}/*********************************************************** * 出队列* ***********************************************************/ Status DeQueue(Queue &Q, int &e){if(Q.rear != Q.front)e = Q.elem[Q.front];else ;Q.front = (Q.front+1)%MAX_QUEUE_NUMBER;return OK;}/*********************************************************** * 广度遍历************************************************************/void BFSTraverse(Graph G,char *name){ArcNode *p;int v,w,u,k=0;Queue Q;int visited[20];for(v=1;v<=G.vexnum;v++) //初始化visited[v]=0;InitQueue(Q);for(v=LocateVex(G,name);k!=2;v=(v+1)%(G.vexnum-1)) //v为输入的字符转化的位序{if(v+1==LocateVex(G,name)) //从v开始走完图的所有顶点k++;if(visited[v]==0){visited[v]=1;printf("%s ",G.vertices[v].data); //访问第v个顶点EnQueue(Q,v); // 进队while(EmptyQueue(Q)!=0){DeQueue(Q,u); //出队p=G.vertices[u].firstarc;while(p!=NULL){w=p->adjvex; //p边的下一个顶点if(visited[w]==0){printf("%s ",G.vertices[w].data);visited[w]=1;EnQueue(Q,w);}p=p->nextarc; //下移指针}}}}}主文件:#include <stdio.h>#include"malloc.h"#include "tuhead.h"#include "stdlib.h"#include "string.h"/************************************************************ 界面控制************************************************************/void main(){printf("\n################################# 图的遍历#################################\n");printf("\n $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n");printf("\n");printf(" 1 ------- 图的创建\n");printf(" 2 ------- 图的深度优先遍历\n");printf(" 3 ------- 图的广度优先遍历\n");printf(" 0 ------- 退出\n");printf("\n $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\n");printf("\n");printf("请输入选择的操作代码(0-3)按回车键结束\n");MenuSelect(1);}/************************************************************ 功能选择************************************************************/void MenuSelect(int w){int select,done;int v;Graph G; char name[10];while (done) {printf("input the operating code : ");scanf("%d",&select);switch(select){case 1: printf("根据要求创建图:\n ");CreateGraph(G);break;case 2: printf("请输入深度优先遍历开始点的名:");scanf("%s",name);v=LocateVex(G,name); //将输入字符找到在顶点数组name对应的序号Vprintf("深度优先遍历:");DFSTravel(G,v);printf("\n");break;case 3: printf("请输入广度优先遍历开始点的名:");scanf("%s",name);printf("广度优先遍历:");BFSTraverse(G,name);printf("\n");break;case 0: done=0; break;default: printf(" ERROR\n");}printf("\n");}}[实验数据与结果]测试数据:实验结果。

图的深度优先遍历(DFS)c++非递归实现

图的深度优先遍历(DFS)c++非递归实现

图的深度优先遍历(DFS)c++⾮递归实现深搜算法对于程序员来讲是必会的基础,不仅要会,更要熟练。

ACM竞赛中,深搜也牢牢占据着很重要的⼀部分。

本⽂⽤显式栈(⾮递归)实现了图的深度优先遍历,希望⼤家可以相互学习。

 栈实现的基本思路是将⼀个节点所有未被访问的“邻居”(即“⼀层邻居节点”)踹⼊栈中“待⽤”,然后围绕顶部节点猛攻,每个节点被访问后被踹出。

读者可以⾃⼰画图分析⼀下,难度并不⼤。

代码写的⽐较随意,仅供参考。

~#include <iostream>#include <stack>using namespace std;#define MaxNode 20#define MAX 2000#define StartNode 1int map[MaxNode+1][MaxNode+1];void dfs_stack(int start, int n){int visited[MaxNode],s_top;for(int i = 0;i <= MaxNode; i++){visited[i] = 0;}visited[start] = 1;stack <int> s;cout<<start<<"";for(int i = 1; i <= n; i++){if(map[i][start] == 1 && !visited[i] ){visited[i] = 1;s.push(i);}}while(!s.empty()){s_top = s.top();visited[s_top] = 1;cout<<s_top<<"";s.pop();for(int i = 1; i <= n; i++){if(map[i][s_top] == 1 && !visited[i] ){visited[i] = 1;s.push(i);}}}}int main(int argc, const char * argv[]) {int num_edge,num_node;int x,y;cout<<"Input number of nodes and edges >"<<endl;cin>>num_node>>num_edge;for(int i =0;i<num_node;i++){for(int j=0;j<num_node;j++){map[i][j] = 0;}}for(int i = 1; i <= num_edge; i++){cin>>x>>y;map[x][y] = map[y][x] = 1;}dfs_stack(StartNode, num_node);return0;}。

深度优先搜索示例代码

深度优先搜索示例代码

深度优先搜索示例代码深度优先搜索(Depth First Search,DFS)是一种用于遍历或搜索树或图的算法。

它通过从根节点或某个指定节点开始,尽可能深地探索每个分支,直到找到目标节点或到达叶子节点为止。

本文将给出一个深度优先搜索的示例代码,帮助读者理解算法的实现过程。

示例代码如下:```class Graph:def __init__(self):self.graph = {}def add_edge(self, vertex, edge):if vertex in self.graph:self.graph[vertex].append(edge)else:self.graph[vertex] = [edge]def dfs(self, start):visited = set()self.dfs_helper(start, visited)def dfs_helper(self, vertex, visited):visited.add(vertex)print(vertex)if vertex in self.graph:for neighbor in self.graph[vertex]:if neighbor not in visited:self.dfs_helper(neighbor, visited)```在示例代码中,首先定义了一个`Graph`类,用于表示图结构。

`Graph`类包含了两个方法:`add_edge`用于添加边,`dfs`用于执行深度优先搜索。

`add_edge`方法用于向图中添加边,其中`vertex`表示起始节点,`edge`表示目标节点。

`dfs`方法用于执行深度优先搜索,其中`start`表示搜索的起始节点。

在深度优先搜索的实现中,我们使用了一个`visited`集合来记录已经访问过的节点,避免重复访问。

`dfs_helper`方法用于递归地进行深度优先搜索,其中`vertex`表示当前访问的节点,`visited`表示已访问节点的集合。

数据结构实验报告图的遍历

数据结构实验报告图的遍历

数据结构实验报告图的遍历一、实验目的本实验旨在通过实践的方式学习图的遍历算法,掌握图的深度优先搜索(DFS)和广度优先搜索(BFS)的实现方法,加深对数据结构中图的理解。

二、实验步骤1. 创建图的数据结构首先,我们需要创建一个图的数据结构,以方便后续的操作。

图可以使用邻接矩阵或邻接表来表示,这里我们选择使用邻接矩阵。

class Graph:def__init__(self, num_vertices):self.num_vertices = num_verticesself.adj_matrix = [[0] * num_vertices for _ in range(num_vertic es)]def add_edge(self, v1, v2):self.adj_matrix[v1][v2] =1self.adj_matrix[v2][v1] =1def get_adjacent_vertices(self, v):adjacent_vertices = []for i in range(self.num_vertices):if self.adj_matrix[v][i] ==1:adjacent_vertices.append(i)return adjacent_vertices2. 深度优先搜索(DFS)DFS是一种遍历图的算法,其基本思想是从图的某一顶点开始,沿着一条路径一直走到最后,然后返回尚未访问过的顶点继续遍历,直到所有顶点都被访问过为止。

def dfs(graph, start_vertex):visited = [False] * graph.num_verticesstack = [start_vertex]while stack:vertex = stack.pop()if not visited[vertex]:print(vertex)visited[vertex] =Truefor neighbor in graph.get_adjacent_vertices(vertex):if not visited[neighbor]:stack.append(neighbor)3. 广度优先搜索(BFS)BFS同样是一种遍历图的算法,其基本思想是从图的某一顶点开始,首先访问其所有邻接点,然后再依次访问邻接点的邻接点,直到所有顶点都被访问过为止。

dfs和bfs算法代码

dfs和bfs算法代码

dfs和bfs算法代码深度优先搜索(DFS)和广度优先搜索(BFS)是常用的图遍历算法,它们可以帮助我们解决很多实际问题。

本文将详细介绍这两种算法的实现原理和应用场景。

一、深度优先搜索(DFS)深度优先搜索是一种递归的搜索算法,它从图的某个顶点开始,沿着一条路径尽可能深地搜索,直到无法继续为止,然后回溯到上一级节点,继续搜索其他路径。

DFS一般使用栈来实现。

DFS的代码实现如下:```def dfs(graph, start):visited = set() # 用一个集合来记录已访问的节点stack = [start] # 使用栈来实现DFSwhile stack:node = stack.pop() # 取出栈顶元素if node not in visited:visited.add(node) # 将节点标记为已访问neighbors = graph[node] # 获取当前节点的邻居节点stack.extend(neighbors) # 将邻居节点入栈return visited```DFS的应用场景很多,比如迷宫问题、拓扑排序、连通分量的计算等。

在迷宫问题中,我们可以使用DFS来寻找从起点到终点的路径;在拓扑排序中,DFS可以用来确定任务的执行顺序;在连通分量的计算中,DFS可以用来判断图是否连通,并将图分割成不同的连通分量。

二、广度优先搜索(BFS)广度优先搜索是一种逐层遍历的搜索算法,它从图的某个顶点开始,先访问该顶点的所有邻居节点,然后再访问邻居节点的邻居节点,依次进行,直到遍历完所有节点。

BFS一般使用队列来实现。

BFS的代码实现如下:```from collections import dequedef bfs(graph, start):visited = set() # 用一个集合来记录已访问的节点queue = deque([start]) # 使用队列来实现BFSwhile queue:node = queue.popleft() # 取出队首元素if node not in visited:visited.add(node) # 将节点标记为已访问neighbors = graph[node] # 获取当前节点的邻居节点queue.extend(neighbors) # 将邻居节点入队return visited```BFS的应用场景也很广泛,比如寻找最短路径、社交网络中的人际关系分析等。

深度优先遍历算法实现及复杂度分析

深度优先遍历算法实现及复杂度分析

深度优先遍历算法实现及复杂度分析深度优先遍历算法(Depth First Search, DFS)是一种常用的图遍历算法,用于查找或遍历图的节点。

本文将介绍深度优先遍历算法的实现方法,并进行对应的复杂度分析。

一、算法实现深度优先遍历算法的基本思想是从图的某个节点出发,沿着深度方向依次访问其相邻节点,直到无法继续下去,然后返回上一层节点继续遍历。

下面是深度优先遍历算法的伪代码:```1. 初始化访问标记数组visited[],将所有节点的访问标记置为false。

2. 从某个节点v开始遍历:- 标记节点v为已访问(visited[v] = true)。

- 访问节点v的相邻节点:- 若相邻节点w未被访问,则递归调用深度优先遍历算法(DFS(w))。

3. 遍历结束,所有节点都已访问。

```二、复杂度分析1. 时间复杂度深度优先遍历算法的时间复杂度取决于图的存储方式和规模。

假设图的节点数为V,边数为E。

- 邻接表存储方式:对于每个节点,需要访问其相邻节点。

因此,算法的时间复杂度为O(V+E)。

- 邻接矩阵存储方式:需要检查每个节点与其他节点的连通关系,即需要遍历整个邻接矩阵。

因此,算法的时间复杂度为O(V^2)。

2. 空间复杂度深度优先遍历算法使用了一个辅助的访问标记数组visited[]来记录每个节点的访问状态。

假设图的节点数为V。

- 邻接表存储方式:访问标记数组visited[]的空间复杂度为O(V)。

- 邻接矩阵存储方式:访问标记数组visited[]的空间复杂度同样为O(V)。

综上所述,深度优先遍历算法的时间复杂度为O(V+E),空间复杂度为O(V)。

三、应用场景深度优先遍历算法在图的遍历和搜索问题中广泛应用。

以下是一些典型的应用场景:1. 连通性问题:判断图中两个节点之间是否存在路径。

2. 非连通图遍历:对于非连通图,深度优先遍历算法可以用于遍历所有连通分量。

3. 寻找路径:在图中寻找从起始节点到目标节点的路径。

dfss 例子

dfss 例子

dfss 例子在深度优先搜索(DFS)的应用中,有一个常见的例子是遍历或搜索树或图的节点。

以下是一个简单的DFS遍历二叉树的例子:假设我们有一个二叉树,其节点值为1、2、3、4、5、6,结构如下:```markdown1```2```/ \2 3/ \4 5\6```我们可以使用DFS来遍历这个二叉树。

以下是使用DFS遍历的C++代码:```cppinclude <iostream>include <stack>using namespace std;struct TreeNode {int val;TreeNode left;TreeNode right;TreeNode(int x) : val(x), left(NULL), right(NULL) {} };void dfs(TreeNode root) {if (root == NULL) return;stack<TreeNode> stk;(root);while (!()) {TreeNode node = ();();cout << node->val << " "; // 输出当前节点值if (node->left) (node->left); // 将左子节点入栈,表示继续深度遍历左子树if (node->right) (node->right); // 将右子节点入栈,表示继续深度遍历右子树}}int main() {TreeNode root = new TreeNode(1);root->left = new TreeNode(2);root->right = new TreeNode(3);root->left->left = new TreeNode(4);root->left->right = new TreeNode(5);root->right->right = new TreeNode(6);dfs(root); // 输出: 1 2 4 5 3 6return 0;}```在这个例子中,我们使用一个栈来模拟深度优先搜索的过程。

图的深度优先遍历详解

图的深度优先遍历详解

图的深度优先遍历详解图的深度优先遍历详解说明1. 深度优先遍历,即先向纵深处挖掘遍历,等这条路⾛不通再回溯2. 设置要开始遍历的第⼀个顶点,然后寻找该顶点的第⼀个邻接顶点,如果第⼀个邻接顶点存在,则从第⼀个邻接顶点⼜重新开始深度优先,寻找它的第⼀个邻接顶点,直到他们的第⼀个邻接顶点不存在或者第⼀个邻接顶点已经被访问,那么寻找它的下⼀个邻接顶点,直到寻找完所有的顶点3. 很明显需要使⽤递归4. 当没有通路的最后⼀个邻接顶点相连的所有顶点全部遍历完时,则回溯判断上⼀个顶点的下⼀个邻接顶点,直到遍历完然后再回溯5. 直到遍历完所有的顶点6. 说明:当当前顶点的第⼀个邻接顶点已经被访问过时,才遍历它的下⼀个邻接顶点7. 源码见下源码及分析深度优先核⼼代码//深度优先算法实现/*** @param isVisited 判断当前顶点是否已经遍历过* @param v 从遍历的当前顶点下标*/public void dfs(boolean[] isVisited, int v) {//先输出当前顶点信息System.out.print(getValueByIndex(v) + "-->");//将当前节点设置为已经访问过isVisited[v] = true;//获取当前节点的第⼀个节点int w = getFirstNeighbor(v);//如果当前顶点存在,则递归遍历while (w != -1) {//依旧需要判断当前顶点是否访问过if (!isVisited[w]) {dfs(isVisited, w);}//如果w节点已经被访问过w = getNextNeighbor(v, w);}}//对dfs进⾏重载,遍历所有的顶点public void dfs() {for (int i = 0; i < getNumOfVertex(); i++) {if (!isVisited[i]) {dfs(isVisited, i);}}}}深度优先遍历代码实现package algorithm.datastructor.graph;import java.util.ArrayList;import java.util.Arrays;/*** @author AIMX_INFO* @version 1.0*/public class Graph {//使⽤邻接矩阵表⽰图//使⽤集合存储图的顶点private ArrayList<String> vertexList;//使⽤⼆维数组即矩阵描述顶点之间的关系private int[][] edges;//边的个数private int numOfEdges;//定义变量判断是否访问过private boolean[] isVisited;//测试public static void main(String[] args) {int n = 5;String[] vertexs = {"A", "B", "C", "D", "E"};//创建图Graph graph = new Graph(n);//添加顶点for (String vertex : vertexs) {graph.insertVertex(vertex);}//连接顶点graph.insertEdge(0, 1, 1);graph.insertEdge(0, 2, 1);graph.insertEdge(1, 2, 1);graph.insertEdge(1, 3, 1);graph.insertEdge(1, 4, 1);//显⽰图graph.showGraph();System.out.println("深度优先遍历");graph.dfs();}//n为顶点的个数public Graph(int n) {edges = new int[n][n];vertexList = new ArrayList<>(n);numOfEdges = 0;isVisited = new boolean[n];}//插⼊顶点public void insertVertex(String vertex) {vertexList.add(vertex);}/*** 添加边** @param v1 顶点在集合中存储的下标* @param v2 顶点在集合中的下标* @param weight 两个顶点之间的权值,0或者1,表⽰是否相连 */public void insertEdge(int v1, int v2, int weight) {edges[v1][v2] = weight;edges[v2][v1] = weight;numOfEdges++;}//返回节点的个数public int getNumOfVertex() {return vertexList.size();}//返回边的个数public int getNumOfEdges() {return numOfEdges;}//返回下标 i 对应的数public String getValueByIndex(int i) {return vertexList.get(i);}//返回v1和v2的权值public int getWeigh(int v1, int v2) {return edges[v1][v2];}//显⽰矩阵public void showGraph() {for (int[] link : edges) {System.out.println(Arrays.toString(link));}}//获取与当前顶点连接的第⼀个邻接顶点public int getFirstNeighbor(int v) {for (int i = 0; i < vertexList.size(); i++) {if (edges[v][i] > 0) {return i;}}return -1;}//根据前⼀个邻接顶点获取下⼀个邻接节点的下标 /*** @param v1 当前顶点* @param v2 当前顶点的第⼀个顶点* @return 返回下⼀个邻接顶点*/public int getNextNeighbor(int v1, int v2) {for (int i = v2 + 1; i < vertexList.size(); i++) { if (edges[v1][i] > 0) {return i;}}return -1;}//深度优先算法实现/*** @param isVisited 判断当前顶点是否已经遍历过 * @param v 从遍历的当前顶点下标*/public void dfs(boolean[] isVisited, int v) {//先输出当前顶点信息System.out.print(getValueByIndex(v) + "-->"); //将当前节点设置为已经访问过isVisited[v] = true;//获取当前节点的第⼀个节点int w = getFirstNeighbor(v);//如果当前顶点存在,则递归遍历while (w != -1) {//依旧需要判断当前顶点是否访问过if (!isVisited[w]) {dfs(isVisited, w);}//如果w节点已经被访问过w = getNextNeighbor(v, w);}}//对dfs进⾏重载,遍历所有的顶点public void dfs() {for (int i = 0; i < getNumOfVertex(); i++) {if (!isVisited[i]) {dfs(isVisited, i);}}}}。

数据结构课设——有向图的深度、广度优先遍历及拓扑排序

数据结构课设——有向图的深度、广度优先遍历及拓扑排序

数据结构课设——有向图的深度、⼴度优先遍历及拓扑排序任务:给定⼀个有向图,实现图的深度优先, ⼴度优先遍历算法,拓扑有序序列,并输出相关结果。

功能要求:输⼊图的基本信息,并建⽴图存储结构(有相应提⽰),输出遍历序列,然后进⾏拓扑排序,并测试该图是否为有向⽆环图,并输出拓扑序列。

按照惯例,先上代码,注释超详细:#include<stdio.h>#include<stdlib.h>#include<malloc.h>#pragma warning(disable:4996)#define Max 20//定义数组元素最⼤个数(顶点最⼤个数)typedef struct node//边表结点{int adjvex;//该边所指向结点对应的下标struct node* next;//该边所指向下⼀个结点的指针}eNode;typedef struct headnode//顶点表结点{int in;//顶点⼊度char vertex;//顶点数据eNode* firstedge;//指向第⼀条边的指针,边表头指针}hNode;typedef struct//邻接表(图){hNode adjlist[Max];//以数组的形式存储int n, e;//顶点数,边数}linkG;//以邻接表的存储结构创建图linkG* creat(linkG* g){int i, k;eNode* s;//边表结点int n1, e1;char ch;g = (linkG*)malloc(sizeof(linkG));//申请结点空间printf("请输⼊顶点数和边数:");scanf("%d%d", &n1, &e1);g->n = n1;g->e = e1;printf("顶点数:%d 边数:%d\n", g->n, g->e);printf("请输⼊顶点信息(字母):");getchar();//因为接下来要输⼊字符串,所以getchar⽤于承接上⼀条命令的结束符for (i = 0; i < n1; i++){scanf("%c", &ch);g->adjlist[i].vertex = ch;//获得该顶点数据g->adjlist[i].firstedge = NULL;//第⼀条边设为空}printf("\n打印顶点下标及顶点数据:\n");for (i = 0; i < g->n; i++)//循环打印顶点下标及顶点数据{printf("顶点下标:%d 顶点数据:%c\n", i, g->adjlist[i].vertex);}getchar();int i1, j1;//相连接的两个顶点序号for (k = 0; k < e1; k++)//建⽴边表{printf("请输⼊对<i,j>(空格分隔):");scanf("%d%d", &i1, &j1);s = (eNode*)malloc(sizeof(eNode));//申请边结点空间s->adjvex = j1;//边所指向结点的位置,下标为j1s->next = g->adjlist[i1].firstedge;//将当前s的指针指向当前顶点上指向的结点g->adjlist[i1].firstedge = s;//将当前顶点的指针指向s}return g;//返回指针g}int visited[Max];//标记是否访问void DFS(linkG* g, int i)//深度优先遍历{eNode* p;printf("%c ", g->adjlist[i].vertex);visited[i] = 1;//将已访问过的顶点visited值改为1p = g->adjlist[i].firstedge;//p指向顶点i的第⼀条边while (p)//p不为NULL时(边存在){if (visited[p->adjvex] != 1)//如果没有被访问DFS(g, p->adjvex);//递归}p = p->next;//p指向下⼀个结点}}void DFSTravel(linkG* g)//遍历⾮连通图{int i;printf("深度优先遍历;\n");//printf("%d\n",g->n);for (i = 0; i < g->n; i++)//初始化为0{visited[i] = 0;}for (i = 0; i < g->n; i++)//对每个顶点做循环{if (!visited[i])//如果没有被访问{DFS(g, i);//调⽤DFS函数}}}void BFS(linkG* g, int i)//⼴度优先遍历{int j;eNode* p;int q[Max], front = 0, rear = 0;//建⽴顺序队列⽤来存储,并初始化printf("%c ", g->adjlist[i].vertex);visited[i] = 1;//将已经访问过的改成1rear = (rear + 1) % Max;//普通顺序队列的话,这⾥是rear++q[rear] = i;//当前顶点(下标)队尾进队while (front != rear)//队列⾮空{front = (front + 1) % Max;//循环队列,顶点出队j = q[front];p = g->adjlist[j].firstedge;//p指向出队顶点j的第⼀条边while (p != NULL){if (visited[p->adjvex] == 0)//如果未被访问{printf("%c ", g->adjlist[p->adjvex].vertex);visited[p->adjvex] = 1;//将该顶点标记数组值改为1rear = (rear + 1) % Max;//循环队列q[rear] = p->adjvex;//该顶点进队}p = p->next;//指向下⼀个结点}}}void BFSTravel(linkG* g)//遍历⾮连通图{int i;printf("⼴度优先遍历:\n");for (i = 0; i < g->n; i++)//初始化为0{visited[i] = 0;}for (i = 0; i < g->n; i++)//对每个顶点做循环{if (!visited[i])//如果没有被访问过{BFS(g, i);//调⽤BFS函数}}}//因为拓扑排序要求⼊度为0,所以需要先求出每个顶点的⼊度void inDegree(linkG* g)//求图顶点⼊度{eNode* p;int i;for (i = 0; i < g->n; i++)//循环将顶点⼊度初始化为0{g->adjlist[i].in = 0;}for (i = 0; i < g->n; i++)//循环每个顶点{p = g->adjlist[i].firstedge;//获取第i个链表第1个边结点指针while (p != NULL)///当p不为空(边存在){g->adjlist[p->adjvex].in++;//该边终点结点⼊度+1p = p->next;//p指向下⼀个边结点}printf("顶点%c的⼊度为:%d\n", g->adjlist[i].vertex, g->adjlist[i].in);}void topo_sort(linkG *g)//拓扑排序{eNode* p;int i, k, gettop;int top = 0;//⽤于栈指针的下标索引int count = 0;//⽤于统计输出顶点的个数int* stack=(int *)malloc(g->n*sizeof(int));//⽤于存储⼊度为0的顶点for (i=0;i<g->n;i++)//第⼀次搜索⼊度为0的顶点{if (g->adjlist[i].in==0){stack[++top] = i;//将⼊度为0的顶点进栈}}while (top!=0)//当栈不为空时{gettop = stack[top--];//出栈,并保存栈顶元素(下标)printf("%c ",g->adjlist[gettop].vertex);count++;//统计顶点//接下来是将邻接点的⼊度减⼀,并判断该点⼊度是否为0p = g->adjlist[gettop].firstedge;//p指向该顶点的第⼀条边的指针while (p)//当p不为空时{k = p->adjvex;//相连接的顶点(下标)g->adjlist[k].in--;//该顶点⼊度减⼀if (g->adjlist[k].in==0){stack[++top] = k;//如果⼊度为0,则进栈}p = p->next;//指向下⼀条边}}if (count<g->n)//如果输出的顶点数少于总顶点数,则表⽰有环{printf("\n有回路!\n");}free(stack);//释放空间}void menu()//菜单{system("cls");//清屏函数printf("************************************************\n");printf("* 1.建⽴图 *\n");printf("* 2.深度优先遍历 *\n");printf("* 3.⼴度优先遍历 *\n");printf("* 4.求出顶点⼊度 *\n");printf("* 5.拓扑排序 *\n");printf("* 6.退出 *\n");printf("************************************************\n");}int main(){linkG* g = NULL;int c;while (1){menu();printf("请选择:");scanf("%d", &c);switch (c){case1:g = creat(g); system("pause");break;case2:DFSTravel(g); system("pause");break;case3:BFSTravel(g); system("pause");break;case4:inDegree(g); system("pause");break;case5:topo_sort(g); system("pause");break;case6:exit(0);break;}}return0;}实验⽤图:运⾏结果:关于深度优先遍历 a.从图中某个顶点v 出发,访问v 。

深度优先搜索算法详解及代码实现

深度优先搜索算法详解及代码实现

深度优先搜索算法详解及代码实现深度优先搜索(Depth-First Search,DFS)是一种常见的图遍历算法,用于遍历或搜索图或树的所有节点。

它的核心思想是从起始节点开始,沿着一条路径尽可能深入地访问其他节点,直到无法继续深入为止,然后回退到上一个节点,继续搜索未访问过的节点,直到所有节点都被访问为止。

一、算法原理深度优先搜索算法是通过递归或使用栈(Stack)的数据结构来实现的。

下面是深度优先搜索算法的详细步骤:1. 选择起始节点,并标记该节点为已访问。

2. 从起始节点出发,依次访问与当前节点相邻且未被访问的节点。

3. 若当前节点有未被访问的邻居节点,则选择其中一个节点,将其标记为已访问,并将当前节点入栈。

4. 重复步骤2和3,直到当前节点没有未被访问的邻居节点。

5. 若当前节点没有未被访问的邻居节点,则从栈中弹出一个节点作为当前节点。

6. 重复步骤2至5,直到栈为空。

深度优先搜索算法会不断地深入到图或树的某一分支直到底部,然后再回退到上层节点继续搜索其他分支。

因此,它的搜索路径类似于一条深入的迷宫路径,直到没有其他路径可走后,再原路返回。

二、代码实现以下是使用递归方式实现深度优先搜索算法的代码:```pythondef dfs(graph, start, visited):visited.add(start)print(start, end=" ")for neighbor in graph[start]:if neighbor not in visited:dfs(graph, neighbor, visited)# 示例数据graph = {'A': ['B', 'C'],'B': ['A', 'D', 'E'],'C': ['A', 'F'],'D': ['B'],'E': ['B', 'F'],'F': ['C', 'E']}start_node = 'A'visited = set()dfs(graph, start_node, visited)```上述代码首先定义了一个用于实现深度优先搜索的辅助函数`dfs`。

实现图的遍历算法实验报告

实现图的遍历算法实验报告

实现图的遍历算法实验报告实现图的遍历算法实验报告⼀实验题⽬: 实现图的遍历算法⼆实验要求:2.1:(1)建⽴如图(p126 8.1)所⽰的有向图 G 的邻接矩阵,并输出之(2)由有向图G的邻接矩阵产⽣邻接表,并输出之(3)再由(2)的邻接表产⽣对应的邻接矩阵,并输出之2.2 (1)输出如图8.1所⽰的有向图G从顶点0开始的深度优先遍历序列(递归算法)(2)输出如图8.1所⽰的有向图G从顶点0开始的深度优先遍历序列(⾮递归算法)(3)输出如图8.1所⽰的有向图G从顶点0开始的⼴度优先遍历序列三实验内容:3.1 图的抽象数据类型:ADT Graph{数据对象V:V是具有相同特性的数据元素的集合,称为顶点集。

数据关系R:R={VR}VR={|v,w∈V且P(v,w),表⽰从v到w的弧,谓词P(v,w)定义了弧的意义或信息}基本操作:CreateGraph( &G, V, VR )初始条件:V是图的顶点集,VR是图中弧的集合。

操作结果:按V和VR的定义构造图G。

DestroyGraph( &G )初始条件:图G存在。

操作结果:销毁图G。

LocateVex( G, u )初始条件:图G存在,u和G中顶点有相同特征。

操作结果:若G中存在顶点u,则返回该顶点在图中位置;否则返回其它信息。

GetVex( G, v )初始条件:图G存在,v是G中某个顶点。

操作结果:返回v的值。

PutVex( &G, v, value )初始条件:图G存在,v是G中某个顶点。

初始条件:图G存在,v是G中某个顶点。

操作结果:返回v的第⼀个邻接顶点。

若顶点在G中没有邻接顶点,则返回“空”。

NextAdjVex( G, v, w )初始条件:图G存在,v是G中某个顶点,w是v的邻接顶点。

操作结果:返回v的(相对于w的)下⼀个邻接顶点。

若w是v 的最后⼀个邻接点,则返回“空”。

InsertVex( &G, v )初始条件:图G存在,v和图中顶点有相同特征。

图的深度广度优先遍历C语言程序

图的深度广度优先遍历C语言程序
printf("请输入顶点数目:");
scanf("%d",&L->num);
printf("请输入各顶点的信息(单个符号):");
for(i=0;i<L->num;i++)
{
fflush(stdin);
scanf("%c",&L->vexs[i]);
}
printf("请输入边权矩阵的信息:");
{ *e=sq.data[(sq.front)]; return 1;}
}
/*******************************************************************பைடு நூலகம்*********/
int QueueIn (SEQQUEUE *sq,DATATYPE x)
for(v2=0;v2<g.num;v2++)
{
if(g.arcs[v1][v2]!=0&&mark[v2]==0)
{
QueueIn(&q,v2);
mark[v2]=1;
printf("%c ",g.vexs[v2]);
}
}
//如果顺序循环队列sq为空,成功返回1,否则返回0
{
if (sq.rear==sq.front)
return(1);
else
return(0);
}
/*****************************************************************************/

图的遍历算法程序

图的遍历算法程序
}
else{
visited[k]=true;
printf("%c ",G.vexs[k]); //访问第k个顶点
for(i=FirstVex(G,k);i>=0;i=NextVex(G,k,i))
if(!visited[i]) DFS(G,i); //对k的尚未访问的邻接顶点i递归调用DFS
#define MAX_VEX 20 //最大顶点个数
#define QUEUE_SIZE (MAX_VEX+1) //队列长度
using namespace std;
bool *visited; //访问标志数组
//图的邻接矩阵存储结构
typedef struct{
char *vexs; //顶点向量
if(i>=0 && i<G.vexnum && j>=0 && j<G.vexnum){ //i,j合理
for(int k=j+1;k<G.vexnum;k++)
if(G.arcs[i][k]!=INFINITY) return k;
}
return -1;
}
}
//主函数
void main(){
int i;
Graph G;
CreateUDN(G);
visited=(bool *)malloc(G.vexnum*sizeof(bool));
printf("\n广度优先遍历: ");
for(i=0;i<G.vexnum;i++)

图的遍历(深度优先遍历和广度优先遍历)

图的遍历(深度优先遍历和广度优先遍历)

遍历规则 从图中某结点v0出发,深度优先遍历(DFS: Depth First Search)图的规则为: 访问v0; 对v0的各个出点v01,v02,…,v0m,每次从它们中按一定方式(也可任选)选取一个未被访问过的结点,从该结点出发按深度优先遍历方式遍历。 然,因为我们没有规定对出点的遍历次序,所以,图的深度优先遍历结果一般不唯一。
20.2 深度优先遍历
例如,对图 20‑1给出的有向图与无向图,一些遍历结果(结点访问次序)为: 左图:从1出发:1,2,4,5;或1,5,2,4 从2出发:2,1,5,4;或2,4,1,5 右图:从a出发:a,b,c,d;或a,b,d,c; … …
A 如果不想让visited或top做为函数参数,也可以在函数中将其定义为static型量。但是,这样的程序是不可再入的,即函数再次被调用时,static型的量也不重新初始化,造成错误!
上面函数中的参数visited和top实质上是中间变量,只是为了避免在递归调用时重新初始化而放在参数表中,造成使用的不方便,为此,做个包装程序: long DFS1(int g[][CNST_NumNodes], long n, long v0, long *resu ) { char *visited; long top=0; visited = new char[n]; for (long i=0; i<n; i++) visited[i]=0; long num=DFS1( g, n, v0, visited, resu, top ); delete visited; return num; }
深度优先遍历非递归算法的一般性描述。
long DFS_NR(图g,结点v0)
单击此处可添加副标题

源代码--数据结构与算法(Python版)chap8 图

源代码--数据结构与算法(Python版)chap8 图
22
最短路径
最短路径是指两个顶点(源点到终 点)之间经过的边上权值之和最少 的路径。
下面介绍两种计算最短路径算法:
迪杰斯特拉(Djikstra)算法
佛洛伊德(Floyd)算法。
23
最短路径
1. 迪杰斯特拉(Djikstra)算法 迪杰斯特拉算法并非一下子求出起始点到结束点的 最短路径,而是一步步求出它们之间顶点的最短路 径,即基于已经求出的最短路径,逐步求得更远顶 点的最短路径,最终达到目的。通过Dijkstra计算图 G中的最短路径时,需要引进两个集合S和U。其中 ,集合S用于存放已求出最短路径的顶点(以及相 应的最短路径长度),集合U用于存放还未求出最 短路径的顶点(以及该顶点到起点的距离)。
u = q.popleft() print(u," ",end="") for w in G[u]:
if w not in visited: q.append(w) visited.add(w)
print('广度深度优先bfs') bfs(G, 0)
16
最小生成树
构造连通图的最小代价生成树称为 最小生成树。 最小生成树实现算法:
11
递归深度优先
from collections import deque def dfs(G, v, visited=set()):
print(v," ",end="") visited.add(v) # 用来存放已经访问过的顶点 # G[v] 是这个顶点的相邻的顶点 for u in G[v]:
24
最短路径
迪杰斯特拉算法具体步骤包括:
步骤1:初始时,S只包含起点s;U包含除s外的其他顶点,且U中顶点 的距离为"起点s到该顶点的距离,若s和v不相邻,则距离为∞。 步骤2:从U中选出距离最短的顶点k,并将顶点k加入到S中;同时,从 U中移除顶点k。 步骤3:更新U中各个顶点到起点s的距离。之所以更新U中顶点的距离 ,是由于上一步中确定了k是求出最短路径的顶点,从而借助中间定点后 的距离可能小于两顶点的直接距离,即 (s,k)+(k,v)可能小于(s,v)。 步骤4: 重复步骤步骤2和步骤3,直到遍历完所有顶点。

深度优先遍历算法和广度优先遍历算法实验小结

深度优先遍历算法和广度优先遍历算法实验小结

深度优先遍历算法和广度优先遍历算法实验小结一、引言在计算机科学领域,图的遍历是一种基本的算法操作。

深度优先遍历算法(Depth First Search,DFS)和广度优先遍历算法(Breadth First Search,BFS)是两种常用的图遍历算法。

它们在解决图的连通性和可达性等问题上具有重要的应用价值。

本文将从理论基础、算法原理、实验设计和实验结果等方面对深度优先遍历算法和广度优先遍历算法进行实验小结。

二、深度优先遍历算法深度优先遍历算法是一种用于遍历或搜索树或图的算法。

该算法从图的某个顶点开始遍历,沿着一条路径一直向前直到不能再继续前进为止,然后退回到上一个节点,尝试下一个节点,直到遍历完整个图。

深度优先遍历算法通常使用栈来实现。

以下是深度优先遍历算法的伪代码:1. 创建一个栈并将起始节点压入栈中2. 将起始节点标记为已访问3. 当栈不为空时,执行以下步骤:a. 弹出栈顶节点,并访问该节点b. 将该节点尚未访问的邻居节点压入栈中,并标记为已访问4. 重复步骤3,直到栈为空三、广度优先遍历算法广度优先遍历算法是一种用于遍历或搜索树或图的算法。

该算法从图的某个顶点开始遍历,先访问起始节点的所有相邻节点,然后再依次访问这些相邻节点的相邻节点,依次类推,直到遍历完整个图。

广度优先遍历算法通常使用队列来实现。

以下是广度优先遍历算法的伪代码:1. 创建一个队列并将起始节点入队2. 将起始节点标记为已访问3. 当队列不为空时,执行以下步骤:a. 出队一个节点,并访问该节点b. 将该节点尚未访问的邻居节点入队,并标记为已访问4. 重复步骤3,直到队列为空四、实验设计本次实验旨在通过编程实现深度优先遍历算法和广度优先遍历算法,并通过对比它们在不同图结构下的遍历效果,验证其算法的正确性和有效性。

具体实验设计如下:1. 实验工具:使用Python编程语言实现深度优先遍历算法和广度优先遍历算法2. 实验数据:设计多组图结构数据,包括树、稠密图、稀疏图等3. 实验环境:在相同的硬件环境下运行实验程序,确保实验结果的可比性4. 实验步骤:编写程序实现深度优先遍历算法和广度优先遍历算法,进行多次实验并记录实验结果5. 实验指标:记录每种算法的遍历路径、遍历时间和空间复杂度等指标,进行对比分析五、实验结果在不同图结构下,经过多次实验,分别记录了深度优先遍历算法和广度优先遍历算法的实验结果。

C源程序-图的建立和遍历

C源程序-图的建立和遍历

图的建立和遍历题目1:用邻接表存储无向图:采用邻接表作为图的存储结构;程序运行时输入图的顶点及边的信息;实现建立图的基本操作;题目2:对题目1建立的图进行深度遍历。

可以从任意顶点出发深度遍历该图;格式化输出:输出顶点的序列,各数据之间用“->”分开;要求实现FirstAdjVex,NextAdjVex,DFS等基本操作;算法描述创建图:包括建立结点的函数CreatVex(Graph *G),以及GreatUDG(Graph *G) ,GreatUDN(Graph *G) ,GreatDG(Graph *G) GreatDN(Graph *G)1提示用户输入图的基本信息:顶点数,边数以及图的基本类型;2通过for循环语句提示用户输入顶点的值;3图Graph结构体类型包括:AdjList用来存储头结点的数组;int类型vexnum 和arcnum,用来表示顶点数和边数的变量;int类型kind,用来存储图的类型。

边ArcNode结构包括:adjvex,ArcNode *nextarc,int info前者表示指向的结点的下标,后者表示指向结点的下一条边结点,最后的变量为边所带的权值信息;4根据图的类型决定是否要使用边中的info变量;5提示用户按照正确的形式输入边的端点以及边上的权值信息;遍历图:包括DFSTraverse(Graph G,VertexType vex)以及DFS(Graph G,int v)两个主要的便历函数。

前者第二个参数表示开始进行便历的顶点,后者的第二个参数表示对图的下标为v的顶点访问。

1遍历前首先建立一个标志数组Visited[],长度为图中结点的数目,用来表示是否访问过一结点,访问前全置为0;2接收用户要求开始访问的顶点,通过函数Adjfound(Graph G,VertexType c)找到改点在图的结点中的下标;3若该下标对应的标志数组的值为0,访问该下标的firstArcNode结点,同时把该结点的在访问标志数组中的值设置为1;若该下标对应的标志数组的值为1,则进行第5步;4继续进行操作2;5在标志数组中查找仍为0的项,得到下标值再进行第1步操作;如果都访问过则遍历结束。

图的遍历操作实验报告

图的遍历操作实验报告

图的遍历操作实验报告一、实验目的本次实验的主要目的是深入理解图的遍历操作的基本原理和方法,并通过实际编程实现,掌握图的深度优先遍历(DepthFirst Search,DFS)和广度优先遍历(BreadthFirst Search,BFS)算法,比较它们在不同类型图中的性能和应用场景。

二、实验环境本次实验使用的编程语言为 Python,开发环境为 PyCharm。

实验中使用的数据结构为邻接表来表示图。

三、实验原理(一)深度优先遍历深度优先遍历是一种递归的图遍历算法。

它从起始节点开始,沿着一条路径尽可能深地访问节点,直到无法继续,然后回溯到上一个未完全探索的节点,继续探索其他分支。

(二)广度优先遍历广度优先遍历则是一种逐层访问的算法。

它从起始节点开始,先访问起始节点的所有相邻节点,然后再依次访问这些相邻节点的相邻节点,以此类推,逐层展开。

四、实验步骤(一)数据准备首先,定义一个图的邻接表表示。

例如,对于一个简单的有向图,可以使用以下方式创建邻接表:```pythongraph ={'A':'B','C','B':'D','E','C':'F','D':,'E':,'F':}```(二)深度优先遍历算法实现```pythondef dfs(graph, start, visited=None):if visited is None:visited = set()visitedadd(start)print(start)for next_node in graphstart:if next_node not in visited:dfs(graph, next_node, visited)```(三)广度优先遍历算法实现```pythonfrom collections import deque def bfs(graph, start):visited ={start}queue = deque(start)while queue:node = queuepopleft()print(node)for next_node in graphnode:if next_node not in visited:visitedadd(next_node)queueappend(next_node)```(四)测试与分析分别使用深度优先遍历和广度优先遍历算法对上述示例图进行遍历,并记录遍历的顺序和时间开销。

图的遍历(实验报告附C++源码)

图的遍历(实验报告附C++源码)

图的遍历一、问题背景若用有向网表示网页的链接网络,其中顶点表示某个网页,有向弧表示网页之间的链接关系。

试设计一个网络蜘蛛系统,分别以广度优先和深度优先的策略抓取网页。

二、需求分析1)首先输入顶点的数量,然后是各顶点对应的字母,再输入各条弧(权值都置为1);2)输出从首个顶点开始的广度优先遍历序列和深度先遍历序列;3)为了达到任意图的遍历(结点名称不一定是数字,可以是任意可见字符),可以自定义一个数组类型,保存该结点的名称和记录是否被访问;4)图使用相邻矩阵来实现;5)测试数据:输入输入顶点数和弧数:8 9输入8个顶点.输入顶点0:a输入顶点1:b输入顶点2:c输入顶点3:d输入顶点4:e输入顶点5:f输入顶点6:g输入顶点7:h输入9条弧.输入弧0:a b 1输入弧1:b d 1输入弧2:b e 1输入弧3:d h 1输入弧4:e h 1输入弧5:a c 1输入弧6:c f 1输入弧7:c g 1输入弧8:f g 1输出广度优先遍历: a b d h e c f g深度优先遍历: a b c d e f g h三、概要设计抽象数据类型为了遍历任意图,定义了如下数据类型,用于存储该结点的名称和记录是否被访问过。

class Node//基本抽象数据类型{public:char ch; //记录名称,如果将这里改成数组,结点名称可以是多个字符int flag;//记录结点是否被访问};class Graph //图类,此类中,封装了图的一些成员和一些必须的成员函数{private:int getSub(char); //获取某名称的下标Node* arrNode; //记录名称和是否访问的数组int numVertex,numEdge;//记录图的顶点数和边数int **matrix; //用一个二维数组记录两点间是否相连,1相连,0断开public:void setCh(char,int); //将数组的arrNode的每一个单元设置一个结点名称Graph(int);~Graph();int getNumVertex();//获得图的顶点数char first(char ch);//获得相邻结点char next(char ch1,char ch2);//获得隔着ch2,但与ch2相邻的结点void setEdge(char,char,int w=1);//设置两顶点的边和权重(权重默认为1)int getMark(char);//获取是否被访问的记录,已访问返回1,未访问返回0void setMark(char);//把已访问的结点,设置标记};算法的基本思想用一个自定义类型的数组,记录每个结点的信息(包括名称、是否被访问),且此数组作为图的成员变量之一;用一个类,对数组进行相应的操作,以便获得所需的信息。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
if(k>=0 && k<G.vexnum){ //k合理
for(int i=0;i<G.vexnum;i++)
if(G.arcs[k][i]!=INFINITY) return i;
}
return -1; if(G.vexs[i]==c) return i;
return -1;
}
//创建无向网
void CreateUDN(Graph &G){
int i,j,w,s1,s2;
char a,b,temp;
printf("输入顶点数和弧数:");
scanf("%d%d",&G.vexnum,&G.arcnum);
temp=getchar(); //接收回车
G.vexs=(char *)malloc(G.vexnum*sizeof(char)); //分配顶点数目
printf("输入%d个顶点.\n",G.vexnum);
for(i=0;i<G.vexnum;i++){ //初始化顶点
int NextVex(Graph G,int i,int j){
if(i>=0 && i<G.vexnum && j>=0 && j<G.vexnum){ //i,j合理
for(int k=j+1;k<G.vexnum;k++)
if(G.arcs[i][k]!=INFINITY) return k;
}
else{
visited[k]=true;
printf("%c ",G.vexs[k]); //访问第k个顶点
for(i=FirstVex(G,k);i>=0;i=NextVex(G,k,i))
if(!visited[i]) DFS(G,i); //对k的尚未访问的邻接顶点i递归调用DFS
G.arcs[i][j]=INFINITY;
printf("输入%d条弧.\n",G.arcnum);
for(i=0;i<G.arcnum;i++){ //初始化弧
printf("输入弧%d:",i);
scanf("%c %c %d",&a,&b,&w); //输入一条边依附的顶点和权值
}
return -1;
}
//深度优先遍历
void DFS(Graph G,int k){
int i;
if(k==-1){ //第一次执行DFS时,k为-1
for(i=0;i<G.vexnum;i++)
if(!visited[i]) DFS(G,i); //对尚未访问的顶点调用DFS
输入顶点6:g
输入顶点7:h
输入9条弧.
输入弧0:a b 1
输入弧1:b d 1
输入弧2:b e 1
输入弧3:d h 1
输入弧4:e h 1
输入弧5:a c 1
输入弧6:c f 1
输入弧7:c g 1
输入弧8:f g 1
深度优先遍历: a b d h e c f g
程序结束.
int arcs[MAX_VEX][MAX_VEX]; //邻接矩阵
int vexnum,arcnum; //图的当前顶点数和弧数
}Graph;
//图G中查找元素c的位置
int Locate(Graph G,char c){
for(int i=0;i<G.vexnum;i++)
temp=getchar(); //接收回车
s1=Locate(G,a);
s2=Locate(G,b);
G.arcs[s1][s2]=G.arcs[s2][s1]=w;
}
}
//图G中顶点k的第一个邻接顶点
int FirstVex(Graph G,int k){
printf("输入顶点%d:",i);
scanf("%c",&G.vexs[i]);
temp=getchar(); //接收回车
}
for(i=0;i<G.vexnum;i++) //初始化邻接矩阵
for(j=0;j<G.vexnum;j++)
}
}
//主函数
void main(){
int i;
Graph G;
CreateUDN(G);
visited=(bool *)malloc(G.vexnum*sizeof(bool));
printf("\n深度优先遍历: ");
for(i=0;i<G.vexnum;i++)
#include <malloc.h>
#define INFINITY 32767
#define MAX_VEX 20 //最大顶点个数
bool *visited; //访问标志数组
//图的邻接矩阵存储结构
typedef struct{
char *vexs; //顶点向量
visited[i]=false;
DFS(G,-1);
printf("\n程序结束.\n");
}
输出结果为(红色为键盘输入的数据,权值都置为1):
输入顶点数和弧数:8 9
输入8个顶点.
输入顶点0:a
输入顶点1:b
输入顶点2:c
输入顶点3:d
输入顶点4:e
输入顶点5:f
相关文档
最新文档