【数据结构】第6章 图 图的存储、DFS、BFS、关键路径

【图的存储、DFS、BFS、关键路径


1、图的邻接矩阵存储

#include <bits/stdc++.h>
using namespace std;
typedef int Status;
#define OK 1;

//----图的邻接矩阵储存表示----
#define MaxInt 32767                        //表示极大值
#define MVNum 100                           //最大顶点数
typedef char VerTexType;                    //假设顶点的数据类型为字符型
typedef int ArcType;                        //假设边的权值类型为整形
int v1, v2, w;

typedef struct 
{
    VerTexType vexs[MVNum];                 //顶点表
    ArcType arcs[MVNum][MVNum];             //邻接矩阵
    int vexnum, arcnum;                     //图当前的点数和边数
}AMGragh;                                   //邻接矩阵(Adjacency Matric)

AMGragh G;

Status LocateVex(AMGragh G, int v)         //返回顶点v在图G中的位置
{
    for(int i = 0; i < G.vexnum; i++)
        if(v == G.vexs[i])
            return i;
}

Status CreateUDN(AMGragh &G)
{//采用邻接矩阵表示法,创建无向图G
    cin>>G.vexnum>>G.arcnum;                //输入总顶点数,总边数
    for(int i = 0; i < G.vexnum; i++)
        cin>>G.vexs[i];                     //依次输入点的信息
    for(int i = 0; i <G.vexnum; i++)        //初始化邻接矩阵,边的权值均置为极大值MaxInt
        for(int j = 0; j <G.vexnum; j++)    
            G.arcs[i][j] = MaxInt;
    for(int k = 0; k < G.arcnum; k++)       //构造邻接矩阵
    {
        cin>>v1>>v2>>w;                     //输入一条边依附的顶点和权值
        int i = LocateVex(G, v1);           //确定v1和v2在G中的位置,即顶点数组的下标
        int j = LocateVex(G, v2);
        G.arcs[i][j] = w;                   //边<v1, v2>的权值置为w
        G.arcs[j][i] = w;                   //边<v1, v2>的对称边<v2, v1>的权值也置为w
    }
    return OK;
}

2、图的邻接表存储

#include <bits/stdc++.h>
using namespace std;
typedef int Status;
#define OK 1;

//-----图的邻接表的存储表示-----
#define MaxInt 32767                        //表示极大值
#define MVNum 100                           //最大顶点数
typedef char VerTexType;                    //假设顶点的数据类型为字符型
typedef int OtherInfo;                      //假设和边相关的信息的数据类型为整形
int v1, v2, w;

typedef struct ArcNode                      //边结点                    
{
    int adjvex;                             //该边所指向的结点的位置
    struct ArcNode *nextarc;                //指向下一条边的指针
    OtherInfo info;                         //和边相关的其他信息
}ArcNode;

ArcNode *p1, *p2;

typedef struct VNode                        //顶点信息
{
    VerTexType data;                        //数据域,存放顶点vi的名称或其他有关信息
    ArcNode *firstarc;                      //指向第一条依附该顶点的边的指针
}VNode, AdjList[MVNum];                     //AdjList表示邻接表的类型

typedef struct 
{
    AdjList vertices;
    int vexnum, arcnum;                     //图当前的顶点数和边数
}ALGragh;                                   //邻接表(Adjacency List)

ALGragh G;
Status LocateVex(ALGragh G, int v)         //返回顶点v在图G中的位置
{
    for(int i = 0; i < G.vexnum; i++)
        if(v1 == G.vertices[i].data)
            return i;
}

Status CreateUDG(ALGragh &G)
{
    cin>>G.vexnum>>G.arcnum;                //输入总顶点数,总边数
    for(int i = 0; i < G.vexnum; i++)
    {
        cin>>G.vertices[i].data;            //输入顶点值
        G.vertices[i].firstarc = NULL;      //初始化标头结点的指针域为空
    }
    for(int k = 0; k < G.arcnum; k++)
    {
        cin>>v1>>v2;                        //输入一条边依附的两个顶点
        int i = LocateVex(G, v1);           //确定v1和v2在G中的位置,即顶点在G.vertices中的的序号
        int j = LocateVex(G, v2);
        p1 = new ArcNode;                   //生成一个新的边结点*p1;
        p1->adjvex = j;                     //邻接点序号为j
        p1->nextarc = G.vertices[i].firstarc;
        G.vertices[i].firstarc = p1;        //将新结点*p1插入顶点vj的边表头部
        p2 = new ArcNode;                   //生成另一个对称的新的边结点*p2;
        p2->adjvex = i;                     //邻接点序号为i
        p1->nextarc = G.vertices[j].firstarc;
        G.vertices[j].firstarc = p1;        //将新结点*p2插入顶点vi的边表头部
    }
    return OK;
}

3、有向图的十字链表存储

#include <bits/stdc++.h>
using namespace std;
typedef int Status;
#define OK 1;

//----有向图的十字链表储存表示----
#define MAX_VERTEX_NUM 20
typedef char VerTexType;
typedef int InfoType;
typedef struct ArcBox
{
    int tailvex, headvex;                   //该弧的头尾和头顶点的位置
    struct ArcBox *hlink, *tlink;            //分别为弧头相同和弧尾相同的链域
    InfoType *info;                         //该弧相关信息的指针
}ArcBox;

typedef struct VexNode
{
    VerTexType data;
    ArcBox *firstin, *firstout;             //分别指向该顶点的第一项入弧和出弧
}VexNode;

typedef struct 
{
    VexNode xlist[MAX_VERTEX_NUM];          //表头向量
    int vexnum, arcnum;                     //有向图的当前顶点数和弧数
}OLGraph;                                   //十字链表(Orthogonal List)


4、无向图的邻接多重表存储

#include <bits/stdc++.h>
using namespace std;
typedef int Status;
#define OK 1;

//----无向图的邻接多重表储存表示----
#define MAX_VERTEX_NUM 20
typedef char VerTexType;
typedef int InfoType;

typedef enum
{
    unvisited, visited                     //枚举unvisited是0,visited是1,注意没有分号
}VisitIf;

typedef struct EBox
{
    VisitIf mark;                           //访问标记
    int ivex, jvex;                         //该边依附的两个顶点的位置
    struct EBox *ilink, *jlink;             //分别指向依附这两个顶点的下一条边
    InfoType *info;                         //该边的信息指针
}EBox;

typedef struct VexBox
{
    VerTexType data;
    EBox *firstedge;                        //指向第一条依附该顶点的边
}VexBox;

typedef struct 
{
    VexBox adjmulist[MAX_VERTEX_NUM];
    int vexnum, arcnum;                     //无向图当前的顶点数和边数
}AMLGraph;                                  //邻接多重表(Adjacency Multilist)

5、DFS

//----任意图的DFS遍历----
bool visited[MVNum];                                                    //访问标志数组,其初值为false

void DFS(Graph G, int v)                                     
{//图G的储存类型待定,下面分类讨论
    cout<<v;
    visited[v] = true;                                                  //访问第v个顶点,并置访问标志数组相应分量值为true
    for(int w = FirstAdjVex(G, v); w >= 0; w = NextAdjVex(G, v, w))     //FirstAdjVex(G, v)表示v的第一个邻接点,NextAdjVex(G, v, w)表示v相对于w的下一个邻接点
        if(!visited[w])                                                 //依次检查v的所有邻接点w,由于不同储存结构此处操作不同,下面函数再具体展开
            DFS(G, w);                                                  //对v的尚未访问的邻接顶点w递归调用DFS
}

void DFSTraverse(Gragh G)
{//图G的储存类型任意,对非连通图G做深度优先遍历
    for(int v = 0; v < G.vexnum; v++)                                   //访问标志数组初始化
        visited[v] = false;
    for(int v = 0; v < G.vexnum; v++)                                   //循环调用DFS
        if(!visited[v])
            DFS(G, v);                                               //对尚未访问的顶点调用DFS
}


//----邻接矩阵的DFS遍历----
bool visited[MVNum];                                                    //访问标志数组,其初值为false

void DFS_AM(AMGragh G, int v)               
{//图G为邻接矩阵类型,从第v个顶点出发深度优先搜索遍历图G
    cout<<v;                                                            //访问第v个顶点,并置访问标志数组相应分量值为true
    visited[v] = true;
    for(int w = 0; w < G.vexnum; w++)                                   //依次检查邻接矩阵v所在的行
        if((G.arcs[v][w] != 0) && (!visited[w]))                        //G.arcs[v][w] != 0表示w是v的邻接点,!visited[w]表示未访问到
            DFS_AM(G, w);                                               //递归调用DFS_AM
}

void DFSTraverse(AMGragh G)
{//图G的储存类型任意,对非连通图G做深度优先遍历
    for(int v = 0; v < G.vexnum; v++)                                   //访问标志数组初始化
        visited[v] = false;
    for(int v = 0; v < G.vexnum; v++)                                   //循环调用DFS
        if(!visited[v])
            DFS_AM(G, v);                                               //对尚未访问的顶点调用DFS
}


//----邻接表的DFS遍历----
bool visited[MVNum];                                                    //访问标志数组,其初值为false

void DFS_AL(ALGragh G, int v)               
{//图G为邻接表类型,从从第v个顶点出发深度优先搜索遍历图G
    cout<<v;                                                            //访问第v个顶点,并置访问标志数组相应分量值为true
    visited[v] = true;
    ArcNode *p;                                                         
    p = G.vertices[v].firstarc;                                         //p指向v的边链表的第一个边结点
    while(p != NULL)
    {
       int w = p->adjvex;                                               //w是v的邻接点
        if(!visited[w])                                                 //如果w未访问
            DFS_AL(G, w);                                               //递归调用DFS_AL
        p = p->nextarc;                                                 //p指向下一个结点
    }
}

void DFSTraverse(ALGragh G)
{//图G的储存类型任意,对非连通图G做深度优先遍历
    for(int v = 0; v < G.vexnum; v++)                                   //访问标志数组初始化
        visited[v] = false;
    for(int v = 0; v < G.vexnum; v++)                                   //循环调用DFS
        if(!visited[v])
            DFS_AL(G, v);                                                  //对尚未访问的顶点调用DFS
}

6、BFS

//----任意图的BFS遍历----
bool visited[MVNum];                                                    //访问标志数组,其初值为false
int u;
void BFS(Gragh G, int v)
{//按广度优先非递归遍历连通图G,图G的储存类型待定,下面分类讨论
    cout<<v;
    visited[v] = true;                                                  //访问第v个顶点,并置访问标志数组相应分量值为true
    InitQueue(Q);                                                       //辅助队列初始化,置空
    EnQueue(Q, v);                                                      //v进队
   int u;
    while(!QueueEmpty(Q))
    {
        DeQueue(Q, u);                                                  //队头元素出队并置为u
        for(int w = FirstAdjVex(G, u); w >= 0; w = NextAdjVex(G, u, w))
            if(!visited[w])                                             //w为u的尚未访问的邻接顶点
            {
                cout<<w;
                visited[w] = true;                                      //访问w,并置访问标志数组相应分量值为true
                EnQueue(Q, w);                                          //w进队
            }
    }
}

//----邻接矩阵的BFS遍历----
void BFS_AM(AMGragh G, int v)
{//按广度优先非递归遍历连通图G
    cout<<v;
    visited[v] = true;                                                  //访问第v个顶点,并置访问标志数组相应分量值为true
    InitQueue(Q);                                                       //辅助队列初始化,置空
    EnQueue(Q, v);                                                      //v进队
    while(!QueueEmpty(Q))
    {
        u = DeQueue(Q);                                                 //队头元素出队并置为u
        for(int w = 0; w < G.vexnum; w++)
            if((G.arcs[u][w] != 0) && (!visited[w]))                    //G.arcs[v][w] != 0表示w是v的邻接点,!visited[w]表示未访问到                                            //w为u的尚未访问的邻接顶点
            {
                cout<<w;
                visited[w] = true;                                      //访问w,并置访问标志数组相应分量值为true
                EnQueue(Q, w);                                          //w进队
            }
    }
}

//----邻接表的BFS遍历----
void BFS_AL(ALGragh G, int v)
{//按广度优先非递归遍历连通图G
    cout<<v;
    visited[v] = true;                                                  //访问第v个顶点,并置访问标志数组相应分量值为true
    ArcNode *p;    
    InitQueue(Q);                                                       //辅助队列初始化,置空
    EnQueue(Q, v);                                                      //v进队
    while(!QueueEmpty(Q))
    {
        u = DeQueue(Q);                                                 //队头元素出队并置为u
        p = G.vertices[u].firstarc;                                     //p指向v的边链表的第一个边结点
        while(p != NULL)
        {
            int w = p->adjvex;                                          //w是v的邻接点
            if(!visited[w])                                             //如果w未访问
                EnQueue(Q, w);                                          //w入队
            p = p->nextarc;                                             //p指向下一个结点
        }
    }
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_碗碗儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值