C || 图的遍历

  • 图的深度遍历和广度遍历
  • 基于的数据结构是图的邻接表结构,详细可以看上一章节(图的存储结构

深度遍历:

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】:

《C || 图的遍历》

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
  • 运行结果:

《C || 图的遍历》

    原文作者:数据结构之图
    原文地址: https://blog.csdn.net/perry0528/article/details/82845343
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞