首页 > 其他分享 >图的遍历及其C语言实现

图的遍历及其C语言实现

时间:2024-08-01 18:53:31浏览次数:15  
标签:遍历 int Graph 及其 DFS C语言 BFS visited 节点

目录

1.为什么需要两种遍历方法?

2.深度优先搜索(Deepth First Search,DFS)

思想:

具体过程:

伪代码:

时间复杂度:

3.广度优先搜索(Breadth First Search,BFS) 

思想:

具体过程:

 伪代码:

 时间复杂度:

图示: 

​编辑 C语言代码演示


1.为什么需要两种遍历方法?

  • 解决不同问题:DFS适用于寻找路径、解决迷宫问题等需要深入探索的场景。BFS适用于寻找最短路径、分层搜索等需要广泛探索的场景。
  • 效率和资源:DFS使用递归或栈实现,适合内存有限但递归深度不大的情况。BFS使用队列实现,适合图的层次不深,但节点数较多的情况。
  • 结果的不同:DFS找到的路径可能不是最短路径,而BFS保证找到的路径是最短路径(无权图)。

         假设小人出迷宫,需要找出从起点到绿色出口的位置:

 根据深度优先遍历的思想:

 小人需要从右上角一直探索到左下角,非常费时费力。

 但如果使用,广度优先遍历呢?

 根据广度优先的思想,层层向外探索:

 小人最后找到的一定是最短路径:

不理解图示?请往下看: 

2.深度优先搜索(Deepth First Search,DFS)

思想

就像在迷宫中行走,选择一个方向不断往前走,直到无法再继续前进时才回头寻找其他路径。

具体过程

  1. 从图的某个起始点开始。
  2. 访问这个节点,并将其标记为已访问。
  3. 选择一个未访问的邻居节点,重复步骤2。如果所有邻居节点都已访问,则回到上一个节点,继续选择未访问的邻居节点。
  4. 直到所有节点都被访问过。

伪代码:

void DFS ( Vertex V )
{ visited[ V ] = true;
    for ( V 的每个邻接点 W )
        if ( !visited[ W ] )
            DFS( W );
}

时间复杂度:

        若有 N个顶点、 E条边,时间复杂度是

用邻接矩阵存储图O(N^2)
用邻接表存储图O(N+E)

3.广度优先搜索(Breadth First Search,BFS) 

思想

        就像在同心圆中层层扩展,从起始点开始,先访问所有与起始点直接相连的节点,再访问与这些节点相连的节点,以此类推。

具体过程

  1. 从图的某个起始点开始。
  2. 访问这个节点,并将其标记为已访问,同时将其邻居节点加入队列。
  3. 从队列中取出一个节点,访问它,并将它的所有未访问的邻居节点加入队列。
  4. 直到队列为空,所有节点都被访问过。

 伪代码

void BFS ( Vertex V )
{ visited[V] = true;
    Enqueue(V, Q);
    while(!IsEmpty(Q)){
        V = Dequeue(Q);
        for ( V 的每个邻接点 W ){
            if ( !visited[W] ) {
                visited[W] = true;
                Enqueue(W, Q);
            }
        }
    }
}

 时间复杂度:

        若有 N个顶点、 E条边,时间复杂度是

用邻接矩阵存储图O(N^2)
用邻接表存储图O(N+E)

图示: 

 C语言代码演示

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define MAX_VERTICES 100

typedef struct Graph {
    int numVertices;
    int adjMatrix[MAX_VERTICES][MAX_VERTICES];
} Graph;

void initializeGraph(Graph *g, int vertices) {
    g->numVertices = vertices;
    int i;
    for (i = 0; i < vertices; i++) {
    	int j;
        for (j = 0; j < vertices; j++) {
            g->adjMatrix[i][j] = 0;
        }
    }
}

void addEdge(Graph *g, int src, int dest) {
    g->adjMatrix[src][dest] = 1;
    g->adjMatrix[dest][src] = 1;  // 如果是无向图
}

// DFS 递归实现
void DFSUtil(Graph *g, int v, bool visited[]) {
    visited[v] = true;
    printf("%d ", v);
	int i;
    for (i = 0; i < g->numVertices; i++) {
        if (g->adjMatrix[v][i] == 1 && !visited[i]) {
            DFSUtil(g, i, visited);
        }
    }
}

void DFS(Graph *g) {
    bool visited[MAX_VERTICES] = {false};
	int v;
    for (v = 0; v < g->numVertices; v++) {
        if (!visited[v]) {
            DFSUtil(g, v, visited);
        }
    }
}

// BFS 实现
void BFS(Graph *g, int startVertex) {
    bool visited[MAX_VERTICES] = {false};
    int queue[MAX_VERTICES];
    int front = 0, rear = 0;

    visited[startVertex] = true;
    queue[rear++] = startVertex;

    while (front != rear) {
        int v = queue[front++];
        printf("%d ", v);
		int i;
        for (i = 0; i < g->numVertices; i++) {
            if (g->adjMatrix[v][i] == 1 && !visited[i]) {
                visited[i] = true;
                queue[rear++] = i;
            }
        }
    }
}

int main() {
    Graph g;
    initializeGraph(&g, 5);

    addEdge(&g, 0, 1);
    addEdge(&g, 0, 4);
    addEdge(&g, 1, 2);
    addEdge(&g, 1, 3);
    addEdge(&g, 1, 4);
    addEdge(&g, 2, 3);
    addEdge(&g, 3, 4);

    printf("Depth First Search (DFS): ");
    DFS(&g);
    printf("\n");

    printf("Breadth First Search (BFS) starting from vertex 0: ");
    BFS(&g, 0);
    printf("\n");

    return 0;
}

标签:遍历,int,Graph,及其,DFS,C语言,BFS,visited,节点
From: https://blog.csdn.net/weixin_65866298/article/details/140780863

相关文章

  • 代码随想录day16 || 513 树左下角值,112 路径之和,116 中序后序遍历构造二叉树
    切片传递问题question:什么情况下传递切片,什么情况下传递切片指针,为什么有时候会修改原始副本,有时候又不会呢?typesli[]intfuncmain(){ slice:=[]int{1} fmt.Printf("slice:%p\n",slice) change1(slice) fmt.Println("=================================") s2:=......
  • Day16 二叉树Part4 常规递归和遍历法的综合应用(二叉树相关)
    目录任务112.路径总和思路113.路径总和II思路106.从中序与后序遍历序列构造二叉树思路105.从前序与中序遍历序列构造二叉树思路心得体会任务112.路径总和给你二叉树的根节点root和一个表示目标和的整数targetSum。判断该树中是否存在根节点到叶子节点的路径,这条路......
  • Java反射机制及其应用
    Java反射机制及其应用引言Java反射机制是Java语言的一项强大特性,它允许程序在运行时查询、访问和修改类、接口、方法、构造函数等的属性和行为。反射机制在动态代理、框架开发、依赖注入等领域有着广泛的应用。本文将介绍反射的基本概念、如何使用反射,以及反射在动态代理......
  • C语言——循环语句
            C语言是结构化的程序设计语言,这里的结构是指:顺序结构、循环结构、选择结构。在C语言中,有三种循环语句,下文将一一介绍如何在C语言编程时使用。1.while语句        while语句的语法形式如下:1while(表达式);2{    语句;    }   ......
  • 【水仙花数】C语言实现输出所有的水仙花数(三位数的)
    需要使用C语言编写程序打印所有的水仙花数首先介绍什么是水仙花数,水仙花数(也称为阿姆斯壮数或自恋数)是指一个n位数,其各位数字的n次方之和等于它本身。例如,对于三位数来说,如果一个三位数的各位数字的立方和等于这个数本身,那么这个数就是水仙花数。例如,对于三位数153:13+53+33=......
  • Diesel CLI 及其命令
    DieselCLI是用于开发阶段调试以及后续部署数据库所使用的命令行工具。安装的最简单的方式是通过cargobinstall。cargo-binstall工具需要独立安装[1]:Set-ExecutionPolicyUnrestricted-ScopeProcess;iex(iwr"https://raw.githubusercontent.com/cargo-bins/cargo-binst......
  • c语言去掉字符串左右两边的空格
    #include<iostream>usingnamespacestd;#include<string.h>#include<stdio.h>/*去掉右边的空格*/char*rtrim(char*str){ intlen=0; inti=0; len=strlen(str); for(i=len;i>0;i--) { if(*(str+(i-1))=='�......
  • 异常概述及其抛出与捕获机制
    文章目录一、异常概述1.1什么是异常1.2引入异常的好处1.3异常处理流程1.4异常处理机制的要求二、异常类型2.1异常类别2.2Exception类的层次三、抛出异常3.1throws关键字3.2throw关键字3.3链式异常3.4throw和throws的区别四、捕获异常(异常处理程序)4.1......
  • C语言----变量与强制类型转换(5)
    目录1.变量1.1变量的创建1.2变量的分类 1.3变量的存储2.强制类型转换1.变量1.1变量的创建前面我们已经了解了数据类型,我们使用类型做什么呢?类型是用来创建变量的那么什么是变量呢?C语言中把经常变化的值称为变量,不变的值称为常量。变量创建的语法形式是这样的......
  • C语言——复合类型
    一、结构体类型的基本使用1.1结构体类型的基本使用1.1.1为什么要用结构体C语言内置的数据类型,除了几种原始的基本数据类型,只有数组属于复合类型,可以同时包含多个值,但是只能包含相同类型的数据,实际使用场景受限。场景:用指针和结构体结合起来构造节点(如链表节点、二叉树结点......