图论是数据结构中最重要的一章。笔者打算将其分为几篇文章发布出来。本篇文章主要实现了图的存储和遍历,由于BFS,所以本节中用到了STL模板中的队列。比较尴尬的是,笔者这里的实现不适用于算法竞赛,可看但不好用,真正算法竞赛中都用数组实现的。但这种繁琐的代码实现有助于加深我们对图的熟悉程度,间接有利于解决图的问题。后面笔者准备发布“图的应用”的代码,会使用笔者认为较为方便的代码风格,同时也会加上例题,加深读者对这些应用的感受。现在校内数据结构课程似乎对数据结构应用代码的不足够重视,笔者认为一方面是因为实现难度较大,不方便考察,另一方面可能就是因为代码风格不适用于实现和解题。
#include"stdio.h"
#include"stdlib.h" //该文件中包含malloc和free()
//函数结果状态代码
#define TRUE 1
#define FALSE 0
#define OK 1
#define ERROR 0
#define INFEASIBLE -1
#define OVERFLOW -2
//Status是函数的类型,其值是函数结果状态代码
typedef int Status;
//邻接矩阵
#define MVNum 100 //最大顶点数
#define MaxInt 32767 //表示两个点之间的距离无穷大,即不存在边
typedef char VerTexType; //假设顶点类型是char
typedef int ArcType; //假设边权类型是int
typedef struct
{
VerTexType vexs[MVNum]; //顶点表
ArcType arcs[MVNum][MVNum]; //邻接矩阵
int vexnum,arcnum; //顶点数和边数
}AMGraph;
//采用邻接矩阵的方法创建无向网
int LocateVex(AMGraph G,VerTexType u) //用于寻找点的下标的函数
{
for (int i = 0;i < G.vexnum;i++)
{
if (u == G.vexs[i]) return i;
}
return -1;
}
Status CreateUDN(AMGraph &G)
{
scanf("%d %d", &G.vexnum, &G.arcnum); //输入顶点和边的总数
for (int i = 0;i < G.vexnum;i++)
{
scanf("%c", &G.vexs[i]); //输入顶点信息
}
for (int i = 0;i < G.vexnum;i++)
{
for (int j = 0;j < G.vexnum;j++)
{
G.arcs[i][j] = MaxInt; //初始化任意两个点之间的距离为无穷大
}
}
for (int k = 0;k < G.arcnum;k++)
{
int v1, v2, w;
scanf("%c %c %d", &v1, &v2, &w);
int i = LocateVex(G, v1);
int j = LocateVex(G, v2);
G.arcs[i][j]=G.arcs[j][i] = w; //因为无向图,对称
}
return OK;
}
//邻接表存储图
//边结点的数据结构
typedef int OtherInfo;
typedef struct ArcNode
{
int adjvex; //该边所指向的顶点的位置
struct ArcNode *nextarc; //指向下一条边的结点
OtherInfo info; //和边相关的信息
}ArcNode;
//表头结点数据类型
typedef struct VNode
{
VerTexType data; //顶点信息
ArcNode * firtarc; //指向第一条边的指针
}VNode,AdjList[MVNum]; //AdjList表示邻接表类型,AdjList v = VNode v[MVNum]
//图结构的定义
typedef struct
{
VNode vertices[MVNum];
int vexnum, arcnum;
}ALGraph;
//采用邻接表的方法创建无向网
int LocateVex(ALGraph G, VerTexType u) //用于寻找点的下标的函数
{
for (int i = 0;i < G.vexnum;i++)
{
if (u == G.vertices[i].data) return i;
}
return -1;
}
Status CreateUDG(ALGraph &G)
{
scanf("%d %d", &G.vexnum, &G.arcnum); //输入顶点和边的总数
for (int i = 0;i < G.vexnum;i++)
{
scanf("%c", &G.vertices[i].data); //输入顶点信息
G.vertices[i].firtarc = NULL;
}
for (int k = 0;k < G.arcnum;k++)
{
VerTexType v1,v2;
scanf("%c %c", &v1, &v2);
int i = LocateVex(G, v1);
int j = LocateVex(G, v2);
ArcNode *p1 = (ArcNode*)malloc(sizeof(ArcNode));
p1->adjvex = j;
p1->nextarc = G.vertices[i].firtarc;
G.vertices[i].firtarc = p1; //利用头插法,将一条边 插入单链表中
//由于无向图,还要再进行一次操作
ArcNode *p2 = (ArcNode*)malloc(sizeof(ArcNode));
p2->adjvex = i;
p2->nextarc = G.vertices[j].firtarc;
G.vertices[j].firtarc = p1; //利用头插法,将一条边 插入单链表中
}
return OK;
}
//图的遍历
//邻接矩阵实现DFS深度优先搜索(时间复杂度为n2)
int visited[MVNum];
void DFS(AMGraph G, int v) //这里每结点用一个整数来表示,结点序号为 1-n
{
printf("%d", v); //访问结点
visited[v] = true;
for (int w = 1;w <= G.vexnum;w++)
{
if (G.arcs[v][w] != 0 && !visited[w])
{
DFS(G, w);
}
}
}
//邻接表实现广度优先搜索
#include<iostream>
using namespace std;
#include<queue>
queue<int>Q; //加入STL模板,便利直接使用队列
int visited2[MVNum];
void BFS(AMGraph G, int v)
{
printf("%d", v);
visited2[v] = true;
Q.push(v);
while (!Q.empty())
{
int u = Q.front();
Q.pop();
for(int w = /*FirstAdjVex(G, u)*/0;w >= 0;w = /*NextAdjVex(G, u, w)*/0) //w为u尚未访问过的邻接顶点,实际操作时遍历邻接表
{
if (!visited[w])
{
printf("%d", w);
visited2[w] = true;
Q.push(w);
}
}
}
}
int main()
{
}