图的BFS和DFS原理及实例分析(java) & 转载 图的DFS和BFS算法

图的BFS和DFS原理及实例分析(java)

https://blog.csdn.net/feilong_csdn/article/details/69386527

图的深度优先遍历(DFS)和广度优先遍历(BFS),DFS利用递归来实现比较易懂,DFS非递归就是将需要的递归的元素利用一个栈Stack来实现,以达到递归时候的顺序,而BFS则是利用一个队列Queue来实现。

package DataStructure;

import java.util.LinkedList;  
import java.util.Queue;  
import java.util.Stack;

public class Graph {   
    private int number = 9;  
    private boolean[] flag;  
    private String[] vertexs = { "A", "B", "C", "D", "E", "F", "G", "H", "I" };  
    private int[][] edges = {   
            { 0, 1, 0, 0, 0, 1, 1, 0, 0 }, 
            { 1, 0, 1, 0, 0, 0, 1, 0, 1 }, 
            { 0, 1, 0, 1, 0, 0, 0, 0, 1 },  
            { 0, 0, 1, 0, 1, 0, 1, 1, 1 }, 
            { 0, 0, 0, 1, 0, 1, 0, 1, 0 }, 
            { 1, 0, 0, 0, 1, 0, 1, 0, 0 },  
            { 0, 1, 0, 1, 0, 1, 0, 1, 0 }, 
            { 0, 0, 0, 1, 1, 0, 1, 0, 0 }, 
            { 0, 1, 1, 1, 0, 0, 0, 0, 0 }   
            };  

    void DFSTraverse() {  
        flag = new boolean[number];  
        for (int i = 0; i < number; i++) {  
            if (flag[i] == false) {// 当前顶点没有被访问  
                DFS(i);  
            }  
        }  
    }  

    void DFS(int i) {  
        flag[i] = true;// 第i个顶点被访问  
        System.out.print(vertexs[i] + " ");  
        for (int j = 0; j < number; j++) {  
            if (flag[j] == false && edges[i][j] == 1) {  
                DFS(j);  
            }  
        }  
    }  

    void DFS_Map(){
        flag = new boolean[number];
        Stack<Integer> stack =new Stack<Integer>();
        for(int i=0;i<number;i++){
            if(flag[i]==false){
                flag[i]=true;
                System.out.print(vertexs[i]+" ");
                stack.push(i);
            }
            while(!stack.isEmpty()){
                int k = stack.pop();
                for(int j=0;j<number;j++){
                    if(edges[k][j]==1&&flag[j]==false){
                        flag[j]=true;
                        System.out.print(vertexs[j]+" ");
                        stack.push(j);
                        break;
                    }
                }

            }
        }
    }

    void BFS_Map(){
        flag = new boolean[number];
        Queue<Integer> queue = new LinkedList<Integer>();
        for(int i=0;i<number;i++){
            if(flag[i]==false){
                flag[i]=true;
                System.out.print(vertexs[i]+" ");
                queue.add(i);
                while(!queue.isEmpty()){
                    int k=queue.poll();
                    for(int j=0;j<number;j++){
                        if(edges[k][j]==1&&flag[j]==false){
                            flag[j] = true;
                            System.out.print(vertexs[j]+" ");
                            queue.add(j);
                        }
                    }
                }
            }
        }
    }

    public static void main(String[] args) {  
        Graph graph = new Graph();  
        System.out.println("DFS递归:");  
        graph.DFSTraverse();
        System.out.println();
        System.out.println("DFS非递归:");  
        graph.DFS_Map();
        System.out.println();  
        System.out.println("BFS非递归:");  
        graph.BFS_Map();
    }  
} 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99

程序运行结果:
这里写图片描述

前言

图的DFS和BFS算法
https://blog.csdn.net/qq_24486393/article/details/50270481


文章主要介绍数据结构知识板块中图的两种不同存储结构下(邻接表和邻接矩阵)BFS和DFS遍历算法。BFS和DFS应用领域不再说明,深搜和广搜的遍历算法十分重要。

DFS


原理:深度优先搜索,顾名思义即为一条道走到黑的搜索策略,行不通退回来换另外一条道再走到黑,依次直到搜索完成。其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。可以通过图示清晰的说明。

图解遍历下图的全部节点:
这里写图片描述

基于邻接矩阵的DFS算法代码实现

void DFS(GraphAMatrix G,int i,int *visited)
{
    int j;
    if(visited[i])
        return ;//若结点被遍历过 返回 
    else
    {
        cout<<i<<endl;
        visited[i]=1;
        //遍历与该结点相邻的结点 (从第一个开始) 
        for(j=0;j<G.numVertexs;j++)
        {
            if(!visited[i]&&G.Edge[i][j])
                DFS(G,j,visited);//从相邻结点的第一个进行递归式深搜遍历 
        }
    }
} 
void DFS_GreahDG(GreapAMstrix G)
{
    int i,j,e;
    int *visited;//为每一个结点设置一个初始标志为未遍历 
    visited=(int *)malloc(sizeof(int)*G.numVertexs);
    memset(visited,0,sizeof(int)*G.numVertexs);
    //对每一个未被遍历结点进行DFS深度搜索 
    for(i=0;i<G.numVertexs;i++)
    {
        if(!visited[i])
            DFS(G,i,visited);//调用深搜算法 
    }
    free(visited);//释放指针 
    printf("\n");
} 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

基于邻接表的DFS算法实现(全)

#include<iostream>
#include<stdlib.h>
#define maxvn 10

using namespace std;
typedef char VertexType;

//定义图的存储数据类型 
typedef struct ArcNode{
    int adjvesx;
    struct ArcNode *nextarc;
    int info;
}ArcNode;
typedef struct VNode{
    VertexType data;
    ArcNode *firstarc; 
}VNode,AdjList[maxvn];
typedef struct{
    AdjList vertices;
    int Vnum,Anum;
}AdjGraph;

//定义一个全局标识数组 
int visited[maxvn];

int LocateVex(char u,AdjGraph G)
{
    int i;
    for(i=0;i<G.Vnum;i++)
    {
        if(u==G.vertices[i].data)
            return i;
    }
    if(i==G.Vnum)
    {
        cout<<"ERROR!"<<endl;
        exit(1); 
    }
    return 0;
}

//创建图 
void CreatAdjGraph_adjList(AdjGraph &G)
{
    ArcNode *p;
    cout<<"Please input Vnum and Anum:"<<endl;
    cin>>G.Vnum>>G.Anum;
    cout<<"Please input Vertices:"<<endl;//创建表头 
    for(int i=0;i<G.Vnum;i++)
    {
        cin>>G.vertices[i].data;
        G.vertices[i].firstarc=NULL;
    }
    cout<<"Please input Arc[i][j]:"<<endl;//创建链表
    for(int k=0;k<G.Anum;k++)
    {
        p=(ArcNode*)malloc(sizeof(ArcNode));
        char v1,v2;
        cin>>v1>>v2;
        int i=LocateVex(v1,G);
        int j=LocateVex(v2,G);
        int w;
        cin>>w;
        p->adjvesx=j;
        p->info=w;
        p->nextarc=G.vertices[i].firstarc;
        G.vertices[i].firstarc=p; 
    } 
}

//深搜算法 
void DFS(AdjGraph G,int i)
{
    ArcNode*p;
    visited[i]=1;
    p=G.vertices[i].firstarc;
    while(p)
    {
        if(!visited[p->adjvesx])
        {
            visited[p->adjvesx]=1;
            cout<<p->adjvesx<<endl;
        }

        p=p->nextarc;
    }
    return;
}

//调用深搜算法 
void DFSTraverse(AdjGraph G)
{
    for(int i=0;i<G.Vnum;i++)
        visited[i]=0;
    for(int i=0;i<G.Vnum;i++)
    {
        if(!visited[i])
            DFS(G,i);
    }
}

//主函数 
int main()
{
    AdjGraph G;
    CreatAdjGraph_adjList(G);
    DFSTraverse(G);
    return 0;
} 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109

BFS


宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。

我们可以图示清楚的了解算法的具体实施过程:
这里写图片描述

基于邻接矩阵的BFS:

void BFS_Graph(GraphAMatrix G){
    //图的广度优先遍历
    int i,j,e;//i j 为循环控制变量 e为取队列元素变量
    CQueue  Q;
    int *visited = (int *)malloc(sizeof(int)*G.numVertexes);//标记数组
    InitCQueue(&Q);
    for(int i=0;i<G.numVertexes;i++){
        //遍历所有顶点 非连通图的情况化 要遍历全部加上循环
        if(!visited[i]){
            printf("%d",i);
            visited[i] = 1;
            EnCQueue(&Q,i);//起点入队列
            while(!CQueue(Q)){//循环操作
                DeQueue(&Q,&e);//出队列
                for(int j=0;j<G.numVertexes;j++){
                    //遍历顶点集合
                    if(!visited[j]&&G.edges[e][j]){
                        //判断当前结点是否被访问过 且与出队结点是否相连
                        printf("%d",j);
                        visited[j] = 1;
                        EnCQueue(&Q,j); 
                    } 
                } 
            } 
        } 
    } 
    free(visited);
    printf("\n");
} 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

基于邻接表的BFS

void BFS_GraphADJList(GraphADJList G){
    //图的广度优先遍历
    int i,j,e;//i j 为循环控制变量 e为取队列元素变量
    CQueue  Q;
    EdgeNode *p; 
    int *visited = (int *)malloc(sizeof(int)*G.numVertexes);//标记数组
    InitCQueue(&Q);
    for(int i=0;i<G.numVertexes;i++){
        //遍历所有顶点 非连通图的情况化 要遍历全部加上循环
        if(!visited[i]){
            printf("%d",i);
            visited[i] = 1;
            EnCQueue(&Q,i);//起点入队列
            while(!CQueue(Q)){//循环操作
                DeQueue(&Q,&e);//出队列
                p = G.adjList[e].firstedge;//从顶点的链表的第一个边结点开始 
                while(p){
                    j = p->adjvex;//记录当前边的终点序号 
                    if(!visited[j]){
                        printf("%d",j);
                        visited[j] = 1;
                        EnCQueue(&Q,j); 
                    } 
                    p = p->next;//移动到下一条边 
                }
            } 
        } 
    } 
    free(visited);
    printf("\n");
} 
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

DFS与BFS比较


DFS深度优先搜索,空间需求较低,不需要BFS需要一个队列保存搜索过程中搜索记录;其次,深搜在搜索过程中要考虑回溯,在搜索HTML链接,爬取数据方面适用颇多;多用于解决连通性问题。

BFS广度优先搜索,空间需求较高,根据其搜索模式,便于求解最短路径问题,上文提到的Dijkstral和prim算法均基于其思想,因为是按层进行搜索,所以很容易求得最短路径。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值