- 图的深度遍历和广度遍历
- 基于的数据结构是图的邻接表结构,详细可以看上一章节(图的存储结构)
深度遍历:
bool visited[100]; //用于表示节点是否被访问的标志位
void DFS(Graph G, VertexType v) {
visited[v] = 1;
printf("%d\n",v);
ArcNode *e = G.vertices[v].first;
while (e) {
VertexType w = e->adjvex;
if(!visited[w])
DFS(G,w);
e = e->next;
}
}
void DFSTraverse(Graph G) {
for(int i = 1; i <= G.vexnum; i++) visited[i] = 0;
for(int i = 1; i <= G.vexnum; i++) {
if (!visited[i])
DFS(G,i);
}
}
图的广度遍历:
- 其中广度遍历的实现调用了之前实现的一个循环队列的接口
bool visited1[100];
void BFSTraverse(Graph G) {
for(int i = 1; i <= G.vexnum; ++i) {
visited1[i] = 0;
}
Queue Q;
InitQueue(&Q);
for (int i = 1; i <= G.vexnum; ++i) {
if(!visited1[i]) {
EnQueue(&Q,i);
visited1[i] = 1;
printf("%d\n",i);
while(!IsEmpty(Q)) {
VertexType u = Top(Q);
DeQueue(&Q);
ArcNode *e = G.vertices[u].first;
while (e) {
VertexType w = e->adjvex;
if(!visited1[w]) {
visited1[w] = 1;
printf("%d\n",w);
EnQueue(&Q, w);
}
e = e->next;
}
}
}
}
DestroyQueue(&Q);
}
下面是包含图的创建的一个基本实现:
- Adj_DFS.c
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "queue.h"
#define Vertex_Num 100
typedef int VertexType;
//存储弧的结点
typedef struct ArcNode {
int adjvex; //该弧所指向的顶点的位置
int info; //该弧的权值
struct ArcNode *next; //指向下一条弧的指针
}ArcNode;
//存储顶点的结点
typedef struct VNode {
VertexType data;
ArcNode *first;//指向第一条依附该顶点的弧的指针
}VNode, AdjList[Vertex_Num];
//图
typedef struct {
AdjList vertices;
int vexnum, arcnum; //图的顶点数和弧数
}Graph;
bool visited[100];
bool visited1[100];
void CreateGraph(Graph *G) {
printf("请输入顶点数,边数:\n");
scanf("%d %d", &G->vexnum, &G->arcnum);
printf("请输入顶点\n");
for (int i = 1; i <= G->vexnum; i++) {
scanf("%d",&G->vertices[i].data);
G->vertices[i].first = NULL;
}
printf("请选择你要建立的存储类型,1表示邻接表,0表示逆邻接表:\n");
int choice;
scanf("%d",&choice);
int vex1, vex2, weight;
if (choice != 1 && choice != 0) {
printf("输入有错,请重新输入\n");
scanf("%d",&choice);
}
if (choice == 1) {
for (int j =1; j <= G->arcnum; j++) {
printf("请输入边的两个顶点以及权值:\n");
scanf("%d%d%d", &vex1, &vex2, &weight);
ArcNode *edge = (ArcNode*)malloc(sizeof(ArcNode));
edge->adjvex = vex2;
edge->info = weight;
ArcNode *e = G->vertices[vex1].first;
if (e == NULL) {
G->vertices[vex1].first = edge;
}
else {
while (e->next != NULL) e = e->next;
e->next = edge;
}
}
}
if (choice == 0) {
for (int j =1; j <= G->arcnum; j++) {
printf("请输入边的两个顶点以及权值:\n");
scanf("%d%d%d", &vex1, &vex2, &weight);
ArcNode *edge = (ArcNode*)malloc(sizeof(ArcNode));
edge->adjvex = vex1;
edge->info = weight;
edge->next = G->vertices[vex2].first;
G->vertices[vex2].first = edge;
}
}
}
void DFS(Graph G, VertexType v) {
visited[v] = 1;
printf("%d\n",v);
ArcNode *e = G.vertices[v].first;
while (e) {
VertexType w = e->adjvex;
if(!visited[w])
DFS(G,w);
e = e->next;
}
}
void DFSTraverse(Graph G) {
for(int i = 1; i <= G.vexnum; i++) visited[i] = 0;
for(int i = 1; i <= G.vexnum; i++) {
if (!visited[i])
DFS(G,i);
}
}
void BFSTraverse(Graph G) {
for(int i = 1; i <= G.vexnum; ++i) {
visited1[i] = 0;
}
Queue Q;
InitQueue(&Q);
for (int i = 1; i <= G.vexnum; ++i) {
if(!visited1[i]) {
EnQueue(&Q,i);
visited1[i] = 1;
printf("%d\n",i);
while(!IsEmpty(Q)) {
VertexType u = Top(Q);
DeQueue(&Q);
ArcNode *e = G.vertices[u].first;
while (e) {
VertexType w = e->adjvex;
if(!visited1[w]) {
visited1[w] = 1;
printf("%d\n",w);
EnQueue(&Q, w);
}
e = e->next;
}
}
}
}
DestroyQueue(&Q);
}
int main()
{
Graph G;
CreateGraph(&G);
for(int i = 1; i <= G.vexnum; i++)
{
printf("|%d|->", G.vertices[i].data);
ArcNode *e = G.vertices[i].first;
while(e != NULL)
{
printf("%d->", e->adjvex);
e = e->next;
}
printf("NULL\n");
}
printf("深度优先遍历\n");
DFSTraverse(G);
printf("广度优先遍历\n");
BFSTraverse(G);
return 0;
}
- queue.h
#ifndef QUEUE_H_
#define QUEUE_H_
#include <stdbool.h>
#define MAXQSIZE 6
#define OK 1
#define ERROR 0
#define OVERFLOW -1
typedef int Item;
typedef struct {
Item *base;
int front;
int rear;
}Queue;
/*initialize the queue*/
void InitQueue(Queue *q);
/*return the length of the queue*/
unsigned int QueueLength(Queue q);
/*Destroy the queue*/
void DestroyQueue(Queue *q);
/*determine if the queue is empty*/
bool IsEmpty(Queue q);
/*determine if the queue is full*/
bool IsFull(Queue q);
/*return the head elem of the queue*/
Item Top(Queue q);
/*return the back elem of the queue*/
Item Back(Queue q);
/*enqueue, insert the rear*/
bool EnQueue(Queue *q, Item e);
/*dequeue, pop the front*/
bool DeQueue(Queue *q);
/*print the queue*/
void PrintQueue(Queue q);
#endif
- queue.c
#include "queue.h"
#include <stdio.h>
#include <stdlib.h>
void InitQueue(Queue *q) {
q->base = (Item*)malloc(MAXQSIZE * sizeof(Item));
if (q->base == NULL)
exit(OVERFLOW);
q->front = 0;
q->rear = 0;
}
/*return the length of the queue*/
unsigned int QueueLength(Queue q) {
return (q.rear - q.front + MAXQSIZE) % MAXQSIZE;
}
/*Destroy the queue*/
void DestroyQueue(Queue *q) {
q->base = NULL;
q->rear = 0;
q->front = 0;
free(q->base);
}
/*determine if the queue is empty*/
bool IsEmpty(Queue q) {
return q.rear == q.front;
}
bool IsFull(Queue q) {
return (q.rear + 1) % MAXQSIZE == q.front;
}
/*return the head elem of the queue*/
Item Top(Queue q) {
return q.base[q.front];
}
/*return the back elem of the queue*/
Item Back(Queue q) {
return q.base[(q.rear - 1 + MAXQSIZE) % MAXQSIZE];
}
/*enqueue, insert the rear*/
bool EnQueue(Queue *q, Item e) {
if (IsFull(*q))
return ERROR;
q->base[q->rear] = e;
q->rear = (q->rear + 1) % MAXQSIZE;
return OK;
}
/*dequeue, pop the front*/
bool DeQueue(Queue *q) {
if(IsEmpty(*q))
return ERROR;
q->front = (q->front + 1) % MAXQSIZE;
return OK;
}
/*print the queue*/
void PrintQueue(Queue q) {
int i, j;
for (i = 0, j = q.front; i < QueueLength(q); i++, j = (j + 1) % MAXQSIZE) {
printf("%d\n",q.base[j]);
}
}
- 用于检验的测试范例,输入文本【in.txt】:
8 18
1 2 3 4 5 6 7 8
1
1 2 1
1 3 1
2 1 1
2 4 1
2 5 1
3 1 1
3 6 1
3 7 1
4 2 1
4 8 1
5 2 1
5 8 1
6 3 1
6 7 1
7 3 1
7 6 1
8 4 1
8 5 1
- 运行结果: