数据结构-基于图的广度优先搜索策略-NOJ20

使用邻接表广度优先搜索图,判断是否存在由顶点vi到vj的路径
在这里插入图片描述
数据结构:

typedef int VertexData;//顶点数据为整型

typedef struct ArcNode
{
    int adjvex;//该弧指向顶点的位置
    struct ArcNode *nextarc;//指向下一条弧的指针
} ArcNode;

typedef struct VertexNode
{
    VertexData data;//顶点数据
    ArcNode *firstarc;//指向该顶点第一条弧的指针
} VertexNode;

typedef struct
{
    VertexNode vertex[MAX_VERTEX_NUM];
    int vernum, arcnum;//图的顶点数和弧数
} AdjList;//基于邻接表的图(Adjacency List Graph)

typedef struct
{
    int elem[MAX_VERTEX_NUM];
    int front;
    int rear;
} SeqQueue;//循环队列,elem[i]存放的值m表示数组位置为m的图的顶点,不是图的顶点的值

完整代码,关键算法有较为详细的注释:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_VERTEX_NUM 1000//最多顶点个数

typedef int VertexData;//顶点数据为整型

typedef struct ArcNode
{
    int adjvex;//该弧指向顶点的位置
    struct ArcNode *nextarc;//指向下一条弧的指针
} ArcNode;

typedef struct VertexNode
{
    VertexData data;//顶点数据
    ArcNode *firstarc;//指向该顶点第一条弧的指针
} VertexNode;

typedef struct
{
    VertexNode vertex[MAX_VERTEX_NUM];
    int vernum, arcnum;//图的顶点数和弧数
} AdjList;//基于邻接表的图(Adjacency List Graph)

typedef struct
{
    int elem[MAX_VERTEX_NUM];
    int front;
    int rear;
} SeqQueue;//循环队列,elem[i]存放的值m表示数组位置为m的图的顶点,不是图的顶点的值

int visited[MAX_VERTEX_NUM];


int LocateVertex(AdjList *G, int v0);//找到值为v0的数组坐标位置
void CreateDN(AdjList *G);
void BreadthFirstSearch(AdjList *G, int v0);//广度优先搜索
void IsPath(AdjList *G, int vi, int vj);//是否存在路径

void InitQueue(SeqQueue *Q);
void EnterQueue(SeqQueue *Q, int x);
void DeleteQueue(SeqQueue *Q, int *x);
int IsEmpty(SeqQueue *Q);

int main()
{
    AdjList g;
    int vi, vj;
    memset(&g, 0, sizeof(g));
    CreateDN(&g);
    scanf("%d%d", &vi, &vj);
    IsPath(&g, vi, vj);
}

int LocateVertex(AdjList *G, int v0)
{
    int i;
    for(i = 0; i < G->vernum; i++)
    {
        if(G->vertex[i].data == v0)
        {
            break;
        }
    }
    return i;
}

void CreateDN(AdjList *G)
{
    int i;
    int vi, vj;
    int advi, advj;
    ArcNode *q;
    ///1.读入顶点数和边数
    scanf("%d%d", &G->vernum, &G->arcnum);

    ///2.初始化
    for(i = 0; i < G->vernum; i++)
    {
        G->vertex[i].firstarc = NULL;
    }
    ///3.读入顶点
    for(i = 0; i < G->vernum; i++)
    {
        scanf("%d", &G->vertex[i].data);
    }

    ///4.读入边
    for(i = 0; i < G->arcnum; i++)
    {
        scanf("%d%d", &vi, &vj);
        //寻找合适的位置插入
        advi = LocateVertex(G, vi);
        advj = LocateVertex(G, vj);

        q = (ArcNode *)malloc(sizeof(ArcNode));
        q->adjvex = advj;
        q->nextarc = G->vertex[advi].firstarc;
        G->vertex[advi].firstarc = q;
    }
}

void IsPath(AdjList *G, int vi, int vj)
{
    int advi, advj;
    advi = LocateVertex(G, vi);
    advj = LocateVertex(G, vj);
    BreadthFirstSearch(G, advi);
    if(visited[advj] == 1)
    {
        printf("yes");
    }
    else
    {
        printf("no");
    }
}

void BreadthFirstSearch(AdjList *g, int v0)
{
    int v;
    ArcNode *p;
    SeqQueue Q;
    InitQueue(&Q);
    ///1.v0置访问标志并入队
    visited[v0] = 1;
    EnterQueue(&Q, v0);
    ///2.如果队列不空,重复以下操作:
    ///①队首元素u出队
    ///②检查u的所有邻接结点w,若w未被访问,则w置访问标志并入队
    while(!IsEmpty(&Q))
    {
        DeleteQueue(&Q, &v);
        p = g->vertex[v].firstarc;
        while(p != NULL)
        {
            if(visited[p->adjvex] == 0)
            {
                visited[p->adjvex] = 1;
                EnterQueue(&Q, p->adjvex);
            }
            p = p->nextarc;

        }
    }
}

void InitQueue(SeqQueue *Q)
{
    Q->front = Q->rear = 0;
}

void EnterQueue(SeqQueue *Q, int x)
{
    Q->elem[Q->rear] = x;
    Q->rear = (Q->rear + 1) % MAX_VERTEX_NUM;
}

void DeleteQueue(SeqQueue *Q, int *x)
{
    *x = Q->elem[Q->front];
    Q->front = (Q->front + 1) % MAX_VERTEX_NUM;
}

int IsEmpty(SeqQueue *Q)
{
	int flag;
    if(Q->front == Q->rear)
    {
        flag = 1;
    }
    else
    {
        flag = 0;
    }
    return flag;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值