图之深搜与广搜

邻接矩阵的定义:

#define MAXVEX 100
typedef char VertexType;
typedef int EdgeType;
struct GraphStruct;
typedef struct GraphStruct *Graph;
struct GraphStruct{
    VertexType vexs[MAXVEX]; /*顶点,下标从0开始*/
    EdgeType edge[MAXVEX][MAXVEX]; /*邻接矩阵*/
    int vertexNum,edgeNum;
};
邻接表的定义:
#define MAXVEX 100 /*最大顶点数*/
typedef char VertexType;
struct GraphStruct;
typedef struct GraphStruct *Graph;

typedef struct ENode{
    int adjVertex;  /*该边所指的顶点的位置*/
    int weight;     /*边的权*/
    struct ENode *nextEdge;  /*指向下一条边的指针*/
}ENode;

typedef struct VNode{
    VertexType data;   /*顶点信息*/
    ENode *firstEdge; /*指向第一条依附该顶点的边的弧指针*/
}VNode;

struct GraphStruct{
    VNode vexs[MAXVEX];
    int vertexNum,edgeNum; /*图的当前顶点数和弧数*/
};


无向带权图(邻接表)

完成void BFS(Graph g,int k)函数,该函数从第k个点开始广度优先遍历图g,遍历过程中把访问过的顶点的visited设置为1(初始为0)。请注意,在测试代码中已经完成int locateVertex(Graph g, VertexType v);函数(在图g中查找顶点v的序号,不存在返回-1),你可以直接调用。

我们这里怎么实现图的深搜:

void DFS(Graph g,int v0)
{
	ENode* p; 
	int w;
	g->vexs[v0].visited=1;
	p=g->vexs[v0].firstEdge;
	while(p!=NULL){//每一个while循环,都是同一个节点的边。 
		w=p->adjVertex;
		if(g->vexs[w].visited==0){
			DFS(g,w);//每一次DFS都是更进一层的循环 
		}
		p=p->nextEdge;
	}
}

实现图的广搜:

void BFS(Graph g,int k)
{
	queue<int> q;
	ENode *p;
	g->vexs[k].visited=1;
	q.push(k);
	int v,w;
	while(q.size()){//循环一次,访问一个节点的所有边
		v=q.front();
		q.pop();
		p=g->vexs[v].firstEdge;
		while(p!=NULL){
			w=p->adjVertex;
			if(g->vexs[w].visited==0){
				g->vexs[w].visited=1;
				q.push(w);//将边对应的节点放到队列里面
			}
		p=p->nextEdge;
		}
	}
} 

无向带权图(邻接矩阵)

在这里我们怎么实现图的深搜:

void DFS(Graph g, int i)  
{  
   
    g->visited[i] = 1;  
    for(int j = 0; j < g->vertexNum; j ++){
    	if(g->edge[i][j] == 1 && g->visited[j] == 0) {
    		 DFS(g,j); 
    	}      
    }           
}  

在这里我们怎么实现图的广搜:

void BFS(Graph g,int i)
{
    queue<int> q;
    q.push(i);
    int v;
    while(q.size()){
	i=q.front();
	q.pop();
	for(int j=0;j<g->vertexNum;j++){
	    if(g->edge[i][j]==1 && g->visited[j]==0){
	        g->visited[j]=1;
                q.push(j);
	    }	
        }                                                                                                    
    }
} 

深搜:


广搜:

### 度优先索 (DFS) 广度优先索 (BFS) 的主要差异 #### 节点访问顺序 度优先索 (DFS) 和广度优先索 (BFS) 在节点访问顺序上存在显著差异。DFS 使用栈(显式的或隐式的函数调用堆栈)来管理待访问的节点,其核心思想是从起始节点出发尽可能地探索每一条分支,直到无法继续为止才回溯到最近的一个未完全探索的节点并重复此过程[^1]。此相反,BFS 利用队列作为辅助数据结构,按照层次依次扩展当前层的所有节点后再进入下一层级,从而确保先发现离起点更近的目标节点[^3]。 #### 数据结构的选择 由于上述不同的访问模式,两者采用了截然不同的底层支持机制——DFS 倾向于使用栈存储临时状态信息以便追踪已处理过的路径;而 BFS 更依赖于先进先出原则运作下的队列以维持逐层推进的状态记录体系[^4]。 #### 时间复杂度空间需求对比分析 就时间效率而言,在理想情况下假设每个顶点最多连接固定数量边的前提下,无论是执行一次完整的遍历还是寻找特定条件满足的第一个解法实例时,两者的渐进运行成本均为 O(V+E),其中 V 表示顶点总数,E代表边数总和[^2] 。然而当考虑实际内存消耗情况时,BFS 可能会因为需要保存大量处于同一级别的候选项而导致更高的峰值占用量;相比之下如果目标位于较层位置或者整个网络呈现稀疏特性的话,则采用递归形式实现简单直观且无需额外开辟大容量缓冲区资源即可完成任务特性的 DFS 显示出了相对优势. #### 应用场景举例说明 - **适用范围**: 当面临涉及最短距离计算(如单源最短路径问题), 或者希望尽快定位靠近初始结点附近的某个符合条件的结果集等问题情境之下 ,通常推荐选用基于 FIFO 队列操作逻辑构建起来的标准版 BFS 方法来进行求解工作. - 对应地,在面对诸如判断是否存在任意一种可达关系、枚举所有可能排列组合方案又或者是针对某些特殊类型的连通分量展开进一步研究探讨等场合里头 ,往往可以借助具备较强灵活性特征同时也更加节省中间过渡环节所需开销特点明显的经典型态化版本定义出来的标准式样化的 DFS 技术手段予以应对处置.[^1] ```python from collections import deque def bfs(graph, start_node): visited = set() queue = deque([start_node]) while queue: node = queue.popleft() # Remove the first element from the queue. if node not in visited: visited.add(node) # Add all unvisited neighbors to the end of the queue. for neighbor in graph[node]: if neighbor not in visited: queue.append(neighbor) def dfs_recursive(graph, current_node, visited=None): if visited is None: visited = set() visited.add(current_node) for next_node in graph[current_node]: if next_node not in visited: dfs_recursive(graph, next_node, visited) return visited ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值