//
// 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);
}