#include
#include
//#include
#define INFINITY INT_MAX // 无穷大
#define INITIAL_VALUE INFINITY // 邻接矩阵初始值
#define INITIAL_PRINT "∞" // 定义初始值的打印值
#define MaxVertexNum 20 // 邻接矩阵最大顶点数
#define OVERFLOW -2 // 空间分配失败、溢出
// 邻接矩阵
typedef char VertexType;
typedef int EdgeType;
typedef int InfoType;
typedef struct {
VertexType Vex[MaxVertexNum]; // 顶点表
EdgeType Edge[MaxVertexNum][MaxVertexNum]; // 边表(邻接矩阵)
int vexnum, arcnum; // 顶点数、边数
}MGraph;
// 邻接表
typedef struct ArcNode { // 边表结点
int adjvex; // 该弧所指向的顶点的位置(下标)
struct ArcNode* next; // 指向下一条弧的指针
InfoType info; //权值
}ArcNode;
typedef struct VNode { // 顶点表结点
VertexType data; // 顶点信息
ArcNode* first; // 指向第一条依附于此顶点的弧的指针
}VNode, AdjList[MaxVertexNum];
typedef struct { // 邻接表
AdjList vertices; // 一维数组的顶点表,各顶点结点内又放置了一个单链表的边表头指针
int vexnum, arcnum; // 图的顶点数和弧数
}ALGraph;
// 返回图的邻接矩阵存储结构中值为v的顶点下标
int LocateVex(MGraph G, VertexType v);
// 创建带权图(网)的邻接矩阵存储结构 flag为true时创建有向图,flag为false时创建无向图
void createMGraph(MGraph& G, bool flag);
// 返回图的邻接表中值为v的顶点下标
int LocateVex(ALGraph G, VertexType v);
// 创建带权图的邻接表存储结构 flag为true时创建有向图,为false时创建无向图
void createALGraph(ALGraph& G, bool flag);
// 从图的邻接表表示转换为邻接矩阵表示
MGraph ALGraphToMGraph(ALGraph algraph);
void printMGraph(MGraph G);
// 定义访问的行为
void visit(VertexType name);
int FirstNeighbor(MGraph G, int v);
int NextNeighbor(MGraph G, int v, int w);
// 广度优先搜索
void BFSTraverse(MGraph G);
void BFS(MGraph G, int v);
// 深度优先搜索
void DFSTraverse(MGraph G);
void DFS(MGraph G, int v);
// 返回图的邻接矩阵存储结构中值为v的顶点下标
int LocateVex(MGraph G, VertexType v) {
for (int i = 0; i < G.vexnum; i++) {
if (G.Vex[i] == v) return i;
}
return -1;
}
// 创建带权图(网)的邻接矩阵存储结构 flag为true时创建有向图,flag为false时创建无向图
void createMGraph(MGraph& G, bool flag) {
scanf("%d %d", &G.vexnum, &G.arcnum); // 首先输入顶点数和边数
// 输入各顶点字母
for (int i = 0; i < G.vexnum; i++) scanf(" %c", &G.Vex[i]);
// 初始化邻接矩阵
for (int i = 0; i < G.vexnum; i++) {
for (int j = 0; j < G.vexnum; j++) {
G.Edge[i][j] = INITIAL_VALUE;
}
}
// 构造邻接矩阵
for (int k = 0; k < G.arcnum; k++) {
VertexType v1, v2; // 顶点
EdgeType w; // 权值
scanf(" %c %c %d", &v1, &v2, &w); // 输入一条边及其权值
// 定位v1和v2在邻接矩阵中的位置
int i = LocateVex(G, v1), j = LocateVex(G, v2);
G.Edge[i][j] = w;
if (flag == false) // 若创建无向图,则对称位置也设置为此值
G.Edge[j][i] = w;
}
}
// 返回图的邻接表中值为v的顶点下标
int LocateVex(ALGraph G, VertexType v) {
for (int i = 0; i < G.vexnum; i++) {
if (G.vertices[i].data == v) return i;
}
return -1;
}
// 创建带权图的邻接表存储结构 flag为true时创建有向图,为false时创建无向图
void createALGraph(ALGraph& G, bool flag) {
scanf("%d %d", &G.vexnum, &G.arcnum); // 首先输入顶点数和边数
// 输入各顶点字母,构造表头向量
for (int i = 0; i < G.vexnum; i++) {
scanf(" %c", &G.vertices[i].data);
G.vertices[i].first = NULL; // 初始化边表头指针
}
// 构造边表
for (int k = 0; k < G.arcnum; k++) {
VertexType v1, v2; InfoType info;
scanf(" %c %c %d", &v1, &v2, &info); // 输入一条边及其权值
int i = LocateVex(G, v1), j = LocateVex(G, v2);
ArcNode* p;
if (!(p = (ArcNode*)malloc(sizeof(ArcNode)))) exit(OVERFLOW);
p->adjvex = j; p->info = info;
// 采用头插法
p->next = G.vertices[i].first;
G.vertices[i].first = p;
if (flag == false) { // 若为无向图,则在另一个顶点处也加入该边
ArcNode* q;
if (!(q = (ArcNode*)malloc(sizeof(ArcNode)))) exit(OVERFLOW);
q->adjvex = i; q->info = info;
// 采用头插法
q->next = G.vertices[j].first;
G.vertices[j].first = q;
}
}
}
// 从图的邻接表表示转换为邻接矩阵表示
MGraph ALGraphToMGraph(ALGraph algraph) {
// 先初始化邻接矩阵所有元素,然后遍历邻接表顶点表每一行,直接填写相应邻接矩阵元素值
MGraph res;
res.vexnum = algraph.vexnum;
res.arcnum = algraph.arcnum;
// 初始化邻接表元素为0
for (int i = 0; i < res.vexnum; i++) {
for (int j = 0; j < res.vexnum; j++) {
res.Edge[i][j] = INITIAL_VALUE;
}
}
for (int i = 0; i < res.vexnum; i++) {
VNode vv = algraph.vertices[i];
res.Vex[i] = vv.data; // 顶点赋值
// 遍历边表
ArcNode* t = vv.first;
while (t != NULL) { // 邻接矩阵赋值
int j = t->adjvex;
res.Edge[i][j] = t->info;
t = t->next;
}
}
return res;
}
void printMGraph(MGraph G)
{
for (int i = 0; i < G.vexnum; i++) {
for (int j = 0; j < G.vexnum; j++) {
if (G.Edge[i][j] == INITIAL_VALUE) {
printf("%s\t", INITIAL_PRINT);
}
else {
printf("%d\t", G.Edge[i][j]);
}
}
printf("\n");
}
}
bool visited[MaxVertexNum]; // 访问标记数组
void visit(VertexType name) {
printf("%c ", name);
}
int FirstNeighbor(MGraph G, int v)
{
return NextNeighbor(G, v, -1);
}
int NextNeighbor(MGraph G, int v, int w)
{
for (int i = w+1; i < G.vexnum; i++) {
if (G.Edge[v][i] != INITIAL_VALUE) {
return i;
}
}
return -1; // 返回小于0的值,说明找不到
}
// 广度优先搜索
void BFSTraverse(MGraph G)
{
// 先初始化标记数组
for (int i = 0; i < G.vexnum; i++) visited[i] = false;
for (int i = 0; i < G.vexnum; i++) {
if (!visited[i])
BFS(G, i);
}
}
// 非递归广度优先算法
void BFS(MGraph G, int v)
{
visit(G.Vex[v]); // 访问初始顶点
visited[v] = true; // 置该点为访问了
VertexType queue[MaxVertexNum]; int front = -1, rear = -1; // 辅助队列Q
rear = (rear + 1) % MaxVertexNum; queue[rear] = v; // 顶点入队列
while (rear != front) { // 队列非空
front = (front + 1) % MaxVertexNum; v = queue[front];// 队头出队列
// 检测v的所有邻接点
for (int w = FirstNeighbor(G, v); w >= 0; w = NextNeighbor(G, v, w)) { // 查找失败时w = -1
if (!visited[w]) {
visit(G.Vex[w]);
visited[w] = true;
rear = (rear + 1) % MaxVertexNum; queue[rear] = w; // 顶点入队列
}
}
}
}
// 深度优先搜索
void DFSTraverse(MGraph G)
{
// 初始化标记数组
for (int v = 0; v < G.vexnum; v++) {
visited[v] = false;
}
for (int v = 0; v < G.vexnum; v++) {
if (!visited[v])
DFS(G, v);
}
}
// 递归算法
void DFS(MGraph G, int v) {
visit(G.Vex[v]);
visited[v] = true;
// 检测v的所有邻接点
for (int w = FirstNeighbor(G, v); w >= 0; w = NextNeighbor(G, v, w)) { // 查找失败时w = -1
if (!visited[w]) {
DFS(G, w);
}
}
}
int main(char* argv[]) {
/**
* 创建邻接矩阵有向图
* 输入:
8 11
1 2 3 4 5 6 7 8
1 2 5
1 4 7
2 3 4
3 1 8
3 6 9
4 3 5
4 6 6
5 4 5
6 5 1
6 1 3
7 8 10
* 输出:
* 广度优先: 1 2 4 3 6 5 7 8
* 深度优先: 1 2 3 6 5 4 7 8
**/
MGraph G;
createMGraph(G, true);
printMGraph(G);
printf("广度优先搜索:\n");
BFSTraverse(G); printf("\n");
printf("深度优先搜索:\n");
DFSTraverse(G); printf("\n");
//ALGraph G2;
//createALGraph(G2, true);
//MGraph G = ALGraphToMGraph(G2);
/**
* 创建邻接矩阵无向图
* 输入:
6 10
1 2 3 4 5 6
1 2 5
1 4 7
2 3 4
3 1 8
3 6 9
4 3 5
4 6 6
5 4 5
6 5 1
6 1 3
* 输出:
* 广度优先: 1 2 3 4 6 5
* 深度优先: 1 2 3 4 5 6
**/
MGraph G2;
createMGraph(G2, false);
printMGraph(G2);
printf("广度优先搜索:\n");
BFSTraverse(G2); printf("\n");
printf("深度优先搜索:\n");
DFSTraverse(G2); printf("\n");
printf("Finish\n");
return 0;
}
测试图
运行效果
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)