图(2)图的深度优先和广度优先遍历算法及求简单路径和最短路径

1. 图的遍历

定义:从给定图中任意指定的顶点出发,按照某种搜索方法沿着图的边访问图中的所有顶点,使每个顶点仅被访问一次。
图的遍历得到的顶点序列称为图的遍历序列。
图的遍历方式有两种:深度优先遍历(DFS)和广度优先遍历(BFS)。

深度优先遍历算法

过程:
(1)从图中某个初始顶点 v v v出发,首先访问初始顶点 v v v
(2)选择一个与顶点 v v v相邻且没被访问过的顶点 w w w,再从 w w w出发进行深度优先搜索,直到图中与当前顶点 v v v邻接的所有顶点都被访问过为止。
算法设计思路:
在这里插入图片描述

#include <iostream>
using namespace std;
#define MaxV 100
typedef char VertexType;
typedef int InfoType;
int visited[MaxV] = {0};
//图的邻接表存储类型定义
struct ArcNode{//边节点类型
    int adjvex;//边的终点编号
    ArcNode* nextarc;//指向下一条边的指针
    InfoType info;//边的信息,如:权
};
struct VNode{//头节点类型
    VertexType data;//顶点信息
    ArcNode* firstarc;//指向第一条边
};
struct ALGraph{//图邻接表类型
    VNode adjlist[MaxV];//邻接表
    int n,e;//顶点数和边数
};
//建立图的邻接表
void CreateAdjListGraph(ALGraph &G)
{
    ArcNode *e;
    cout << "输入顶点数:" << endl;
    cin >> G.n; //输入当前图的顶点数
    cout << "输入边数:" << endl;
    cin >> G.e;    //输入当前图的边数
    cout << "输入顶点信息" << endl;
    for(int i = 0; i < G.n; i++)    //建立顶点表
    {
        cin >> G.adjlist[i].data;   //输入顶点信息
        G.adjlist[i].firstarc = NULL;   //将表边指针置为空
    }
    cout << "输入边的两个顶点及其权重" << endl;
    for(int k = 0; k < G.e; k++)
    {
        int i, j, w;
        cin >> i >> j >> w; //输入边的两个顶点和边上的权重
        e = new ArcNode;   //创建一个表边节点指针
        e->adjvex = j;
        e->info = w;
        e->nextarc = G.adjlist[i].firstarc;
        G.adjlist[i].firstarc = e;
        //因为是无向图,彼此相对称
        e = new ArcNode;   //创建一个表边节点指针
        e->adjvex = i;
        e->info = w;
        e->nextarc = G.adjlist[j].firstarc;
        G.adjlist[j].firstarc = e;
    }
}
void DFS(ALGraph G, int v){//深度优先遍历
    ArcNode *p;
    int w;
    printf("%d ",v);
    visited[v] = 1;
    p = G.adjlist[v].firstarc;//p指向v的第一个邻接点
    while (p != nullptr){//循环访问v的所有邻接点
        w = p->adjvex;//邻接点的编号
        if (visited[w] == 0)
            DFS(G,w);//递归遍历w
        p = p->nextarc;//指向下一个邻接点
    }
}
广度优先遍历算法

在这里插入图片描述
在这里插入图片描述

void BFS(ALGraph G, int v){//广度优先遍历
    ArcNode *p; int w,i;
    int qu[MaxV], rear, front;//循环队列
    rear = front = 0;
    int visited1[MaxV] = {0};
    printf("%d ",v);
    visited1[v] = 1;
    rear = (rear +1) % MaxV;
    qu[rear] = v;//v进队
    while(rear != front){//队不为空时循环
        front = (front + 1) % MaxV;
        w = qu[front];//出队并赋给w
        p = G.adjlist[w].firstarc;//找w的第一个邻接点
        while(p != nullptr){//访问w的所有未访问的邻接点并进队
            if(visited1[p->adjvex] == 0){
                printf("%d ",p->adjvex);//访问并标记
                visited1[p->adjvex] = 1;
                rear = (rear + 1) % MaxV;//相邻顶点进队
                qu[rear] = p->adjvex;
            }
            p = p->nextarc;//找下一个邻接顶点
        }
    }
}
int main()
{
    ALGraph G;
    CreateAdjListGraph(G);
    cout << "深度优先遍历结果为:" << endl;
    DFS(G,1);
    cout << "广度优先遍历结果为:" << endl;
    BFS(G,1);
    return 0;
}

运行结果:
在这里插入图片描述

2. 图遍历的应用
基于DFS的应用

例1:图G采用邻接表存储,设计算法判断顶点u–>v是否有简单路径。
思路:从u开始进行深度优先遍历,当搜索到v时表明从u到v有简单路径。

int visited[MaxV] = {0};
bool ExistPath(ALGraph G, int u, int v){//判断u到v是否有简单路径
    visited[u] = 1;
    if (u == v) return true;
    ArcNode *p; int w;
    p = G.adjlist[u].firstarc;
    if(p != nullptr){
        w = p->adjvex;
        if (visited[w] == 0)
            ExistPath(G,w,v);
        p = p->nextarc;
    }
}

例2:图G采用邻接表存储,设计算法输出图G中从顶点u到v的一条简单路径。

int visited1[MaxV] = {0};
void FindPath(ALGraph G, int u, int v, int path[], int d){//输出从顶点u到v的一条简单路径
    ArcNode *p; int w,i;
    visited1[u] = 1;
    d++; path[d] = u;
    if (u == v){//找到一条路径后输出并返回
        printf("一条简单路径为:");
        for(i=0;i<=d;i++) printf("%d",path[i]);
        printf("\n");
        return;//找到一条后返回
    }
    p = G.adjlist[u].firstarc;//p指向顶点u的第一个相邻点
    while(p!=nullptr){
        w = p->adjvex;
        if (visited1[w] == 0)
            FindPath(G,w,v,path,d);
        p = p->nextarc;
    }
}

例3:图G采用邻接表存储,设计算法输出图G中从顶点u到v的长度为l的所有简单路径。
在这里插入图片描述

int visited[MaxV] = {0};
void FindAllPath(ALGraph G, int u, int v, int l, int path[], int d){//输出u到v的长度为l的所有简单路径
    ArcNode *p; int w,i;
    visited[u] = 1;
    d++; path[d] = u;
    if (u == v && d == l){//输出一条路径
        for(i=0;i<=d;i++) printf("%d",path[i]);
        printf("\n");
        //return;因为要找所有的,所以不返回
    }
    p = G.adjlist[u].firstarc;//p指向顶点u的第一个相邻点
    while(p!=nullptr){
        w = p->adjvex;
        if (visited[w] == 0)
            FindAllPath(G,w,v,l,path,d);
        p = p->nextarc;
    }
    visited[u] = 0;//回溯,使该顶点可以重新使用
}
基于BFS的应用

例4:设计算法求不带权无向连通图G中从u到v的一条最短路径。

void ShortPath(ALGraph G, int u, int v){//求u到v的最短路径
    ArcNode* p; int w,i;
    Quere qu[MaxV];//定义非循环队列
    int rear = -1, front = -1;
    int visited[MaxV] = {0};
    rear++;//顶点u进队
    qu[rear].data = u;
    qu[rear].parent = -1;
    while(front != rear){//队不空时循环
        front++;//出队
        w = qu[front].data;
        //若找到v,输出逆路径
        if(w == v){
            i = front;
            while(qu[i].parent != -1){
                printf("%2d",qu[i].data);
                i = qu[i].parent;
            }
            printf("%2d\n",qu[i].data);
            break;
        }
        p = G.adjlist[w].firstarc;
        //将w未访问过的邻接点进队
        while(p != nullptr){
            if(visited[p->adjvex] == 0){
                visited[p->adjvex] = 1;
                rear++;
                qu[rear].data = p->adjvex;
                qu[rear].parent = front;//进队顶点的前一顶点正是现在的出队元素
            }
            p = p->nextarc;
        }
    }
}

  • 10
    点赞
  • 78
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值