408数据结构学习笔记——图的广度优先搜索、深度优先搜索

简介: 408数据结构学习笔记——图的广度优先搜索、深度优先搜索

1.广度优先搜索

1.1.广度优先搜索的概念

广度优先搜索(Breadth-First-Search, BFS),类似二叉树层次遍历。以v为起点,依次访问和v有路径相同且路径长度为1,2,……的顶点

#define MaxVertexNum 100
bool visited[MaxVertexNum];    //标记是否访问过
void BTS(Graph G, int v){    //从顶点v出发
    Queue Q;
    initQueue(Q);
    visit(v);    //访问v
    visited[v] = true;    //visited数组中下标v的元素改为true
    EnQueue(Q, v);    //v入队
    while(!IsEmpty(Q)){
        DeQueue(Q, v);    //取出队头元素
        int w;
        for(w = FirstNeighbor(G, v); w >= 0; w = NextNeighbor(G, v, w)){
            //检测所有v的邻接点
            if (!visit[w]){    //w当前未访问过
                visit(w);    //访问w
                visit[w] = true;    //visited数组中下标w的元素改为true
                EnQueue(Q, w);    //将w入队
            }//if
        }//for
    }//while
}

非连通图或非强连通图,在执行完BTS后,可能还会有剩余的顶点没有访问到,因此,要重新调用BTS函数继续进行遍历

bool visited[MaxVertexNum];
void BTS(Graph G, int v){
    visit(v);
    visited[v] = true;
    Queue Q;
    InitQueue(Q);
    EnQueue(Q, v);
    while(!IsEmpty(Q)){
        DeQueue(Q, v);
        int w;
        for (w = FirstNeighbor(G, v); w >= 0; w = NextNeighbor(G, v, w)){
            if (!visited[w]){
                visit(w);
                visited[w] = true;
                EnQueue(Q, W);
            }//if
        }//for
    }//while
}
void BTS_G(Graph G){
    for (int i = 0; i < G.verNum; i++) visited[i] = false;    //初始化visited数组
    //当前visited数组下标i的元素为false,调用BTS函数
    for (int i = 0; i < G.verNum; i++) if (!visited[i]) BTS(G, i);
}    

1.2.广度优先搜索的可变性

邻接矩阵唯一→广度优先遍历序列唯一

邻接表不唯一→广度优先遍历序列不唯一

1.3.广度优先搜索性能

空间复杂度:图中每个顶点都需要入队一次,最坏情况下是O(|V|)

时间复杂度:分为访问各顶点的时间和探索各条边的时间

  1. 邻接矩阵,访问V个结点,需要O(|V|),查找需遍历V行(顶点数),每行V个顶点,需要O(|gif.gif|),故时间复杂度为O(|gif.gif|)
  2. 邻接表,访问V个结点,需要O(|V|),查找E个边,需要O(|E|),故时间复杂度为O(|V|+|E|)

2.深度优先搜索

2.1.深度优先搜索的概念

首先访问起点v,然后访问与之邻接且未被访问的顶点w,再访问与w邻接且未被访问的顶点u,直到不能再继续向下访问时,依次退回到最近被访问的顶点,如果还有邻接且未被访问的顶点,则访问那个顶点,循环这个过程,直至图中所有顶点都被访问过

bool visited[MaxVertexNum];
void DFS(Graph G, int v){
    visit(v);
    visited[v] = true;
    int w;
    for (w = FirstNeighbor(G, v); w >= 0; w = NextNeighbor(G, v, w)) DFS(G, w);
}
void DFS_G(Graph G){
    for (int i = 0; i < G.verNum; i++) visit[i] = false;
    for (int i = 0; i < G.verNum; i++) if (!visit[i]) DFS(G, i);
}

2.2.深度优先搜索的性能

空间复杂度:最好O(1):中间一点连着其他顶点,栈仅需一个空间;最坏O(|V|):一条线,需要全部依次压入栈中

时间复杂度:

  1. 邻接矩阵 O(|gif.gif|)
  2. 邻接表O(|V|+|E|)

3.图的遍历和图的连通性

无向图:DFS/BFS函数调用次数 = 连通分量数

有向图:起始顶点到其他顶点都有路径,则仅需一次;强连通图从任意一个顶点出发,都仅需一次

4.王道课后题

1e8e1fe9a5cb42e18a08849017f4e9c7.png

无向图是树→连通图且没有回路 || 有 n - 1 条边的连通图

//广度搜索,对应连通图且没有回路
bool visited[MaxVertexNum];
bool IsTree(ALGraph G) {
  //初始化visited数组
  for (int i = 0; i < MaxVertexNum; i++) visited[i] = false;
  Queue Q;
  InitQueue(Q);
  //寻找图中的第一个数据
  int p;
  for (p = 0; p < MaxVertexNum; p++) if (G.vertices[p].data) break;
    int temp = p;
    int count = 0;    //标记访问了多少个顶点
  //将p入队
  EnQueue(Q, p);
  while (!IsEmpty(Q)) {
    //出队队头元素
    DeQueue(Q, p);
    //当前顶点p未扫描过,则进入标记扫描,并且找到所有与它邻接的顶点,并依次入队
    if (!visited[p]) {
      visited[p] = true;
            count++;
      for (int q = FirstNeighbor(G, p); q >= 0; q = NextNeighbor(G, p, q)){
                EnQueue(Q, q);
            }
    }
    //扫描过p,存在回路
    else return false;
  }
    //访问顶点个数不等于顶点总数,非连通图
    if (count != G.verNum) return false;
    else return true;
}
//DFS,对应有 n - 1 条边的连通图
bool visited[MaxVertexNum];
bool IsTree(ALGraph G) {
  //初始化visited数组为false
  for (int i = 0; i < G.verNum; i++) visited[i] = false;
  //vCount记录遍历顶点数,eCount记录遍历边数
  int vCount = 0, eCount = 0;
  //遍历G中的每个顶点
  for (int i = 0; i < G.verNum; i++) {
    if (!visited[i]) DFS(G, vCount, eCount, i);
  }
  //满足条件顶点数=已遍历顶点数,并且边数为n - 1
  //无向图的存储中每条边存储两次
  if (vCount == G.verNum && 2 * eCount + 2 == G.arcNum) return true;
  else return false;
}
void DFS(ALGraph G, int& vCount, int& eCount, int v) {
  if (!visited[v]) {
    visited[v] = true;
    //访问顶点数+1
    vCount++;
  }
  for (int w = FistNeighbor; w >= ; w = NextNeighbor) {
    //访问边数+1
    eCount++;
    DFS(G, vCount, eCount, w);
  }
}

279d37289af54c87aa00fb1be1c055a6.png

#define MaxVertexNum 100
typedef struct ArcNode{
    struct ArcNode *next;
    int adjVertex;
}ArcNode;
typedef struct VNode{
    ArcNode *next;
    elemtype data;
}VNode, adjList[MaxVertexNum];
typedef struct{
    adjList vertices;
    int verNum, arcNum;
}ALGraph;
typedef struct Stack{
    int top;
    elemtype data[MaxVertexNum];
}Stack;
bool visited[MaxVertexNum];
void DFS(ALGraph G, int v){
    //初始化visited数组
    for (int i = 0; i < MaxVertexNum; i++) visited[i] = false;
    Stack S;
    InitStack(S);
    int i, j;
    //访问v,并将v压入栈中
    visited[v] = true;
    push(S, v);
    //循环直到栈空
    while(!IsEmpty(S)){
        //弹出栈顶元素
        pop(S, i);
        //访问i所有的邻接结点
        for (j = FirstNeighbor(G, i); j >= 0; j = NextNeighbor(G, i, j)){
            //将j压入栈中
            if (!visited[j]) {
                visited[j] = true;
                push(S, j);
            }
        }//for
    }//while
}

d270b0fa92e14707a5f8731525fdf921.png

//广度搜索
#define MaxVertexNum 100
typedef struct ArcNode{
    struct ArcNode *next;
    int adjVertex;
}ArcNode;
typedef struct VNode{
    ArcNode *first;
    elemtype data;
}VNode, AdjList[MaxVertexNum];
typedef struct ALGraph{
    AdjList vertices;
    int verNum, arcNum;
}ALGraph;
typedef struct Queue{
    elemtype data[MaxVertexNum];
    int rear, front;
}Queue;
bool visited[MaxVertexNum];
bool BFS_iToj(Graph G, int i, int j){
    for (int i = 0; i < G.verNum; i++) visited[i] = false;
    Queue Q;
    InitQueue;
    EnQueue(Q, i);
    int w, v;
    while (!IsEmpty(Q)){
        DeQueue(Q, v);
        if (!visited[v]) {
            //v == j, ij存在路径,返回true
            if (j == v) return true;
            visited[v] = true;
            for (w = FistNeighbor(G, v); w >= 0; w = NextNeighbor(G, v, w)){
                if (!visited[w]) EnQueue(Q, w);
            }
        }//if
    }//while
    //ij没有路径,返回false
    return false;
}
//深度搜索
#define MaxVertexNum 100
typedef struct ArcNode{
    struct ArcNode *next;
    int adjVertex;
 }ArcNode;
typedef struct VNode{
    ArcNode *first;
    elemtype data;
}VNode, AdjList[MaxVertexNum];
typedef struct ALGraph{
    int verNum, arcNum;
    AdjList vertices;
}ALGraph;
typedef struct Stack{
    elmetpye data[MaxVertexNum];
    int top;
}Stack;
bool visited[MaxVertexNum];
bool DFS_iToj(ALGraph G, int i, int j){
    Stack S;
    InitStack(S);
    for (int temp = 0; temp < G.verNum; temp++) visited[temp] = false;
    push(S, i);
    visited[i] = 0;
    int v, w;
    while (!IsEmpty(S)){
        pop(S, v);
        for (w = FirstNeighbor(G, v); w >= 0; w = NextNeighbor(G, v, w)){
            //w == j, ij存在路径,返回true
            if (w == j) return true;
            if (!visited[w]) {
                visited[w] = true;
                push(S, w);
            }
        }//for
    }//while
    return false;
}





相关文章
|
2月前
|
算法 测试技术 定位技术
数据结构与算法——DFS(深度优先搜索)
数据结构与算法——DFS(深度优先搜索)
|
6月前
|
存储 算法
数据结构===图
数据结构===图
|
3月前
|
存储 JSON NoSQL
redis基本数据结构(String,Hash,Set,List,SortedSet)【学习笔记】
这篇文章是关于Redis基本数据结构的学习笔记,包括了String、Hash、Set、List和SortedSet的介绍和常用命令。文章解释了每种数据结构的特点和使用场景,并通过命令示例演示了如何在Redis中操作这些数据结构。此外,还提供了一些练习示例,帮助读者更好地理解和应用这些数据结构。
redis基本数据结构(String,Hash,Set,List,SortedSet)【学习笔记】
|
2月前
|
机器学习/深度学习 存储 算法
数据结构与算法——BFS(广度优先搜索)
数据结构与算法——BFS(广度优先搜索)
|
5月前
|
算法 Python
逆袭之路!用 Python 玩转图的 DFS 与 BFS,让数据结构难题无处遁形
【7月更文挑战第12天】图的遍历利器:DFS 和 BFS。Python 中,图可表示为邻接表或矩阵。DFS 沿路径深入,回溯时遍历所有可达顶点,适合找路径和环。BFS 层次遍历,先近后远,解决最短路径问题。两者在迷宫、网络路由等场景各显神通。通过练习,掌握这些算法,图处理将游刃有余。
65 3
|
5月前
|
存储 算法 Python
“解锁Python高级数据结构新姿势:图的表示与遍历,让你的算法思维跃升新高度
【7月更文挑战第13天】Python中的图数据结构用于表示复杂关系,通过节点和边连接。常见的表示方法是邻接矩阵(适合稠密图)和邻接表(适合稀疏图)。图遍历包括DFS(深度优先搜索)和BFS(广度优先搜索):DFS深入探索分支,BFS逐层访问邻居。掌握这些技巧对优化算法和解决实际问题至关重要。**
45 1
|
6月前
|
数据采集 算法 Java
Java数据结构与算法:图算法之广度优先搜索(BFS)
Java数据结构与算法:图算法之广度优先搜索(BFS)
|
6月前
|
算法 Java
Java数据结构与算法:图算法之深度优先搜索(DFS)
Java数据结构与算法:图算法之深度优先搜索(DFS)
|
6月前
|
存储
数据结构学习记录——如何建立图(邻接矩阵、邻接表-图节点的结构、创建并初始化、插入变、完整图的建立)
数据结构学习记录——如何建立图(邻接矩阵、邻接表-图节点的结构、创建并初始化、插入变、完整图的建立)
82 0
|
6月前
|
存储 算法
数据结构学习记录——图应用实例-六度空间(题目描述、算法思路、伪代码及解读、图解)
数据结构学习记录——图应用实例-六度空间(题目描述、算法思路、伪代码及解读、图解)
61 0