[算法]图_广度优先_邻接矩阵&邻接表实现

//
//  main.cpp
//  7.5DFS_WFS_adjoinMatrix
//
//  Created by 郭宸羽 on 21/10/2022.
//
#include <stdlib.h>
#include <stdio.h>
#define MAXVEX 10
#define INFI 2147483647

//0.临接矩阵存储结构——————————————————————————————————————————————————————————————————————————
typedef struct MGraph
{
    int vexs[MAXVEX];
    int edges[MAXVEX][MAXVEX];
    int v_num, edge_num;
}MGraph;
//—————————————————————————————————————————————————————————————————————————————————————————

//1.辅助队列_链式存储及相关操作描述——————————————————————————————————————————————————————————————————————————

typedef struct QNode
{
    int element;
    struct QNode* next_n;
}QNode;

typedef struct Queue{
    QNode * p_head;
    QNode * p_tail;
    int node_num;
}Queue;

void InitialQ(Queue &queue)
{
    queue.p_head = (QNode*)calloc(1, sizeof(QNode));
    queue.p_tail = queue.p_head;
    queue.node_num = 0;
}

bool IsEmpty(Queue *p_Q)
{
    if(p_Q->node_num == 0)
        return true;
    else
        return false;
}

void EnQueue(Queue *p_queue,int element){
    QNode * tem = (QNode*)calloc(1, sizeof(QNode));
    tem->element = element;
    tem->next_n = NULL;
    p_queue->p_tail->next_n = tem;
    p_queue->p_tail = tem;
    p_queue->node_num++;
}

void DeQueue(Queue *p_queue,int *e)//e为出队元素,在广度优先遍历时候需要1)打印 2)新入队元素的依据
{
    QNode*tem = p_queue->p_head;
    *e = p_queue->p_head->next_n->element;
    
    p_queue->p_head = p_queue->p_head->next_n;
    p_queue->p_head->element = 0;//将链表结点转换为头节点
    
    free(tem);
    tem = nullptr;
    p_queue->node_num--;
}
//——————————————————————————————————————————————————————————————————————————————————————

void CreateMGraph(MGraph *G)
{
    G->edge_num = 15;
    G->v_num = 9;
    
    G->vexs[0]='A';
    G->vexs[1]='B';
    G->vexs[2]='C';
    G->vexs[3]='D';
    G->vexs[4]='E';
    G->vexs[5]='F';
    G->vexs[6]='G';
    G->vexs[7]='H';
    G->vexs[8]='I';

    for(int i = 0;i<G->v_num;i++)
    {
        for(int j=0;j< G->v_num;j++)
        {
            G->edges[i][j] = INFI;
        }
    }
    
    G->edges[0][1]=1;
    G->edges[0][5]=1;

    G->edges[1][2]=1;
    G->edges[1][8]=1;
    G->edges[1][6]=1;
    
    G->edges[2][3]=1;
    G->edges[2][8]=1;
    
    G->edges[3][4]=1;
    G->edges[3][7]=1;
    G->edges[3][6]=1;
    G->edges[3][8]=1;

    G->edges[4][5]=1;
    G->edges[4][7]=1;

    G->edges[5][6]=1;
    
    G->edges[6][7]=1;
    
    for(int i = 0; i<G->v_num;i++)
    {
        for(int j = i;j<G->v_num;j++)
        {
            G->edges[i][j] = G->edges[j][i] = 0;
        }
    }
}

bool visisted_arr[MAXVEX];//顶点访问标志数组

//2.邻接矩阵的广度优先遍历———————————————————————————————————————————————
void BFS(MGraph G)
{
    int i,j,v;
    Queue seq_Q;
    //1)初始化
    //1.1)初始化顶点访问数组
    for(i = 0;i<G.v_num;i++)
    {
        visisted_arr[i] = false;
    }
    //1.2)初始化辅助队列
    InitialQ(seq_Q);
    
    //2)BFS遍历访问——⚠️BFS核心
    for(i = 0;i<G.v_num;i++)
    {
        if(visisted_arr[i] == false)//if当前顶点未被访问过 ⇒ 进行访问的相关操作
        {
            visisted_arr[i] = true;//2.1)将顶点在visited数组中标记为访问过
            printf("%c ",G.vexs[i]);//2.2)对该顶点进行访问操作
            EnQueue(&seq_Q, G.vexs[i]);//2.3)将当前顶点入队
            //⚠️BFS实现的核心中的核心
            while(IsEmpty(&seq_Q) == false)
            {
                DeQueue(&seq_Q, &v);
                for(j = 0;j<G.v_num;j++)//2.4)在临接矩阵中进行判断,是否其他顶点与当前顶点存在边且访问过
                {
                    if(G.edges[i][j] == 1 && visisted_arr[j] == false)
                    {
                        visisted_arr[j] = true;
                        printf("%c ",G.vexs[j]);
                        EnQueue(&seq_Q, j);
                    }
                }
            }
        }
        else
        {
            continue;
        }
    }
}

//2.邻接表的广度优先遍历(⭐️为不同)——————————————————————————————————————————————
void BFSL(MGraph G)
{
    int i;EdgeNode *p;
    Queue seq_Q;
    //1)初始化
    //1.1)初始化顶点访问数组
    for(i = 0;i<G.v_num;i++)
    {
        visisted_arr[i] = false;
    }
    //1.2)初始化辅助队列
    InitialQ(seq_Q);
    
    //2)BFS(邻接表)遍历访问——⚠️BFS核心
    for(i = 0;i<G.v_num;i++)
    {
        if(visisted_arr[i] == false)//if当前顶点未被访问过 ⇒ 进行访问的相关操作
        {
            visisted_arr[i] = true;//2.1)将顶点在visited数组中标记为访问过
            printf("%c ",GL->adjList[i].data);//⭐️2.2)对邻接表的顶点表对应的顶点进行访问操作
            EnQueue(&seq_Q, i);//2.3)将当前顶点下标入队
            
            //⚠️BFS实现的核心中的核心
            while(IsEmpty(&seq_Q) == false)
            {
                DeQueue(&seq_Q, &i);
                p = GL->adjList[i].firstedge;//⭐️指针指向邻接链表第一个节点
                while(p != NULL)//2.4)⭐️当邻接链表所指向的临接节点不为空时
                {
                    if( visisted_arr[j] == false)
                    {
                        visisted_arr[p->adjv_index] = true;//当前指针指向邻接链表第一个节点,在临接连表里标记为ture
                        printf("%c ",GL->adjList[p->adjv_index].data);
                        EnQueue(&seq_Q, p->adjv_index);
                    }
                    p = p->next;//⭐️
                }
            }
        }
        //其实临接链表相对于邻接矩阵宽度优先遍历实现更简单,少了一个判断两个节点是否有关联,因为邻接表里存在着的节点全是跟顶点表(adjList[])中的顶点有关的,而邻接矩阵是用矩阵元素所在行或列下标表示顶点,对应元素的值表示两顶点间是否有关联,存在不代表一定相关!
        else
        {
            continue;
        }
    }
}

int main()
{
    MGraph G;
    CreateMGraph(&G);
    BFS(G);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值