1.BFS:广度优先(breadth first search)(队列)
1.1基于邻接矩阵的广度优先
queue.h
#ifndef __QUEUE_H__
#define __QUEUE_H__
#include <stdio.h>
#define SIZE 512
//函数声明
int is_empty(void);
int is_full(void);
void enqueue(int c);
int dequeue(void);
extern int queue[SIZE]; // 便于另一个.c代码使用
#endif
queue.c
#include "queue.h"
int queue[SIZE];
int head = 0, tail = 0;
//循环队列入队
void enqueue(int n)
{
queue[tail] = n;
tail = (tail+1) % SIZE;
}
//出队
int dequeue(void)
{
int n;
n = queue[head];
head = (head + 1) % SIZE;
return n;
}
//判断队列是否为空
int is_empty(void)
{
return head == tail;
}
//判断队列为满
int is_full(void)
{
return (tail + 1) % SIZE == head;
}
DFS_AMG.c
#include <stdio.h>
#include <stdlib.h>
#include "queue.h" //包含队列
#define MAX 100
// 邻接矩阵的图
struct AMG_Graph
{
int vex_num, edge_num; // 顶点个数,边个数
char Vex[MAX]; // 顶点信息(一维数组)
int Edge[MAX][MAX]; // 顶点关系信息 0/1(二维数组)
};
//函数声明
struct AMG_Graph *Creat_AMG_Graph(void);
void Show_AMG_Graph(struct AMG_Graph *graph);
int search_vex(struct AMG_Graph *graph, char c);
void BFS_AMG(struct AMG_Graph *graph);
// 主函数
int main(void)
{
struct AMG_Graph *d_graph; // 有向图指针
d_graph = Creat_AMG_Graph(); // 创建邻接矩阵
Show_AMG_Graph(d_graph);
printf("traverse the graph through BFS:\n");
BFS_AMG(d_graph); // 广度优先邻接矩阵有向图
return 0;
}
struct AMG_Graph *Creat_AMG_Graph(void)
{
int i,j;
char u,v;
struct AMG_Graph *graph;
graph = (struct AMG_Graph *)malloc(sizeof(struct AMG_Graph));
printf("please enter the number of vex: ");
scanf("%d", &graph->vex_num);
printf("please enter the number of edge: ");
scanf("%d", &graph->edge_num);
while(getchar() != '\n'); // 消灭回车
printf("please enter the vertex:\n");
for(i = 0; i < graph->vex_num; i++)
{
graph->Vex[i] = getchar();
while(getchar() != '\n');
}
// 初始化二维数组
for(i = 0; i < graph->vex_num; i++)
{
for(j = 0; j < graph->vex_num; j++)
graph->Edge[i][j] = 0;
}
// 输入顶点
while(graph->edge_num--)
{
printf("please enter the vex that connect each other by edge:\n");
u = getchar();
while(getchar() != '\n');
v = getchar();
while(getchar() != '\n');
i = search_vex(graph, u);
j = search_vex(graph, v);
if(i != -1 && j != -1)
//graph->Edge[i][j] = graph->Edge[j][i] = 1; // 无向图
graph->Edge[i][j] = 1; // 有向图 唯一区别
else
{
printf("wrong vex, enter again.\n");
graph->edge_num++;
}
}
return graph;
}
// 显示
void Show_AMG_Graph(struct AMG_Graph *graph)
{
int i,j;
printf("show the vertex:\n");
for(i = 0; i < graph->vex_num; i++)
printf("%c ", graph->Vex[i]);
printf("\n");
printf("show the adjacency matrices:\n");
for(i = 0; i < graph->vex_num; i++)
{
for(j = 0; j < graph->vex_num; j++)
printf("%d\t", graph->Edge[i][j]);
printf("\n");
}
}
// 查找位置
int search_vex(struct AMG_Graph *graph, char c)
{
int i;
for(i = 0; i < graph->vex_num; i++)
{
if(c == graph->Vex[i])
return i;
}
return -1;
}
// 广度优先邻接矩阵有向图
void BFS_AMG(struct AMG_Graph *graph)
{
int u;
int i,j;
int visited[MAX] = {0};
for(j = 0; j < graph->vex_num; j++) // 非连通
{
if(visited[j] == 0)
{
printf("%c ", graph->Vex[j]);
visited[j] = 1;
enqueue(j);
while(!is_empty())
{
u = dequeue();
for(i = 0; i < graph->vex_num; i++)
{
if(graph->Edge[u][i] == 1 && visited[i] == 0)
{
visited[i] = 1;
enqueue(i);
printf("%c ",graph->Vex[i]);
}
}
}
}
}
printf("\n");
}
有向图输出结果
无向图输出结果
1.2基于邻接表的广度优先
queue.h queue.c 相同
BFS_ALG.c
#include <stdio.h>
#include <stdlib.h>
#include "queue.h"
#define MAX 100
//邻接点表
struct AdjNode
{
int index;
struct AdjNode *next;
};
//节点表
struct VexNode
{
char node;
struct AdjNode *first;
};
//邻接表
struct ALG_Graph
{
int vex_num, edge_num; // 顶点个数,边个数
struct VexNode Vex[MAX]; // 节点信息
};
struct ALG_Graph *Create_ALG_Graph(void);
int search_vex(struct ALG_Graph *graph, char c);
void create_adj_node_list(struct ALG_Graph *graph, int i, int j);
void Show_ALG_Graph(struct ALG_Graph *graph);
void BFS_ALG(struct ALG_Graph *graph);
// 主函数
int main(void)
{
struct ALG_Graph *d_graph;
d_graph = Create_ALG_Graph();
Show_ALG_Graph(d_graph);
printf("traverse the graph through BFS:\n");
BFS_ALG(d_graph); // 广度优先邻接表有向图
return 0;
}
// 节点表
struct ALG_Graph *Create_ALG_Graph(void)
{
int i, j;
char u, v;
struct ALG_Graph *graph;
graph = (struct ALG_Graph *)malloc(sizeof(struct ALG_Graph));
printf("please enter the number of vex: ");
scanf("%d", &graph->vex_num);
printf("please enter the number of edge: ");
scanf("%d", &graph->edge_num);
while(getchar() != '\n'); // 消灭回车
//节点信息
printf("please enter the vertex:\n");
for(i = 0; i < graph->vex_num; i++)
{
graph->Vex[i].node = getchar();
while(getchar() != '\n');
}
//指针部分设为空
for(i = 0; i < graph->vex_num; i++)
{
graph->Vex[i].first = NULL;
}
// 输入顶点信息
while(graph->edge_num--)
{
printf("please enter the vex that connect each other by edge:\n");
u = getchar();
while(getchar() != '\n');
v = getchar();
while(getchar() != '\n');
i = search_vex(graph, u);
j = search_vex(graph, v);
if(i != -1 && j != -1)
create_adj_node_list(graph, i, j); // 创建邻接点表
else
{
printf("wrong vex, enter again.\n");
graph->edge_num++;
}
}
return graph;
}
// 创建邻接点表(重点)
void create_adj_node_list(struct ALG_Graph *graph, int i, int j)
{
struct AdjNode *s = (struct AdjNode *)malloc(sizeof(struct AdjNode));
s->index = j;
s->next = graph->Vex[i].first;
graph->Vex[i].first = s;
}
// 查找位置
int search_vex(struct ALG_Graph *graph, char c)
{
int i;
for(i = 0; i < graph->vex_num; i++)
{
if(c == graph->Vex[i].node)
return i;
}
return -1;
}
// 显示
void Show_ALG_Graph(struct ALG_Graph *graph)
{
int i;
struct AdjNode *t;
printf("show the ALG Graph:\n");
for(i = 0; i < graph->vex_num; i++)
{
printf("%c: ", graph->Vex[i].node);
t = graph->Vex[i].first;
while(t != NULL)
{
printf("%d ", t->index);
t = t->next;
}
printf("\n");
}
}
// 广度优先邻接表有向图
void BFS_ALG(struct ALG_Graph *graph)
{
int u;
int n;
int i;
struct AdjNode *p;
int visited[MAX] = {0};
for(i = 0; i < graph->vex_num; i++) // 非连通
{
if(visited[i] == 0)
{
printf("%c ", graph->Vex[i].node);
visited[i] = 1;
enqueue(i);
while(!is_empty()) // 队列不为空
{
u = dequeue(); // 编号出队列
p = graph->Vex[u].first;
while(p)
{
n = p->index;
if(visited[n] == 0)
{
visited[n] = 1;
enqueue(n);
printf("%c ", graph->Vex[n].node);
}
p = p->next;
}
}
}
}
printf("\n");
}
2.DFS深度优先(栈)
2.1基于邻接矩阵的深度优先
stack.h
#ifndef __STACK_H__
#define __STACK_H__
#include <stdio.h>
extern int stack[512];
extern int top;
void push(int c);
int pop(void);
int is_empty(void);
#endif
stack.c
扫描二维码关注公众号,回复:
15954733 查看本文章
#include "stack.h"
int stack[512];
int top = 0;
//入栈
void push(int c)
{
stack[top++] = c;
}
//出栈
int pop(void)
{
return stack[--top];
}
//判断是否为空
int is_empty(void)
{
return top == 0;
}
DFS_AMG.c
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
#define MAX 100
int stack[512];
// 邻接矩阵的图
struct AMG_Graph
{
int vex_num, edge_num; // 顶点个数,边个数
char Vex[MAX]; // 顶点信息(一维数组)
int Edge[MAX][MAX]; // 顶点关系信息 0/1(二维数组)
};
//函数声明
struct AMG_Graph *Creat_AMG_Graph(void);
void Show_AMG_Graph(struct AMG_Graph *graph);
int search_vex(struct AMG_Graph *graph, char c);
void DFS_AMG(struct AMG_Graph *graph);
// 主函数
int main(void)
{
struct AMG_Graph *d_graph; // 有向图指针
d_graph = Creat_AMG_Graph(); // 创建邻接矩阵
Show_AMG_Graph(d_graph);
printf("traverse the graph through DFS:\n");
DFS_AMG(d_graph); // 深度优先邻接矩阵有向图
return 0;
}
//
struct AMG_Graph *Creat_AMG_Graph(void)
{
int i,j;
char u,v;
struct AMG_Graph *graph;
graph = (struct AMG_Graph *)malloc(sizeof(struct AMG_Graph));
printf("please enter the number of vex: ");
scanf("%d", &graph->vex_num);
printf("please enter the number of edge: ");
scanf("%d", &graph->edge_num);
while(getchar() != '\n'); // 消灭回车
printf("please enter the vertex:\n");
for(i = 0; i < graph->vex_num; i++)
{
graph->Vex[i] = getchar();
while(getchar() != '\n');
}
// 初始化二维数组
for(i = 0; i < graph->vex_num; i++)
{
for(j = 0; j < graph->vex_num; j++)
graph->Edge[i][j] = 0; // 有向图
}
// 输入顶点
while(graph->edge_num--)
{
printf("please enter the vex that connect each other by edge:\n");
u = getchar();
while(getchar() != '\n');
v = getchar();
while(getchar() != '\n');
i = search_vex(graph, u);
j = search_vex(graph, v);
if(i != -1 && j != -1)
graph->Edge[i][j] = 1;
else
{
printf("wrong vex, enter again.\n");
graph->edge_num++;
}
}
return graph;
}
// 显示
void Show_AMG_Graph(struct AMG_Graph *graph)
{
int i,j;
printf("show the vertex:\n");
for(i = 0; i < graph->vex_num; i++)
printf("%c ", graph->Vex[i]);
printf("\n");
printf("show the adjacency matrices:\n");
for(i = 0; i < graph->vex_num; i++)
{
for(j = 0; j < graph->vex_num; j++)
printf("%d\t", graph->Edge[i][j]);
printf("\n");
}
}
// 查找位置
int search_vex(struct AMG_Graph *graph, char c)
{
int i;
for(i = 0; i < graph->vex_num; i++)
{
if(c == graph->Vex[i])
return i;
}
return -1;
}
void DFS_AMG(struct AMG_Graph *graph)
{
int i, j;
int u;
int visited[MAX] = {0};
for(i = 0; i < graph->vex_num; i++) // 防止非连通图漏掉点
{
if(visited[i] == 0) // 没有访问
{
printf("%c ", graph->Vex[i]);
visited[i] = 1;
push(i);
while(!is_empty())
{
u = stack[top-1]; // 访问栈顶内容
for(j = 0; j < graph->vex_num; j++)
{
if((graph->Edge[u][i] == 1) && (visited[i] == 0))
{
visited[i] = 1;
push(j);
printf("%c ",graph->Vex[j]);
break; // 关键
}
}
if(j == graph->vex_num) // 访问到头没有满足条件的
pop(); // 出栈
}
}
}
printf("\n");
}
// 输出 a b c d e f g
2.2 基于邻接表的深度优先
stack.h
#ifndef __STACK_H__
#define __STACK_H__
#include <stdio.h>
extern int stack[512];
extern int top;
void push(int c);
int pop(void);
int is_empty(void);
#endif
stack.c
#include "stack.h"
int stack[512];
int top = 0;
//入栈
void push(int c)
{
stack[top++] = c;
}
//出栈
int pop(void)
{
return stack[--top];
}
//判断是否为空
int is_empty(void)
{
return top == 0;
}
DFS_ALG.c
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
#define MAX 100
//邻接点表
struct AdjNode
{
int index;
struct AdjNode *next;
};
//节点表
struct VexNode
{
char node;
struct AdjNode *first;
};
//邻接表
struct ALG_Graph
{
int vex_num, edge_num; // 顶点个数,边个数
struct VexNode Vex[MAX]; // 节点信息
};
struct ALG_Graph *Create_ALG_Graph(void);
int search_vex(struct ALG_Graph *graph, char c);
void create_adj_node_list(struct ALG_Graph *graph, int i, int j);
void Show_ALG_Graph(struct ALG_Graph *graph);
void DFS_ALG(struct ALG_Graph *graph);
// 主函数
int main(void)
{
struct ALG_Graph *d_graph; // 有向图
d_graph = Create_ALG_Graph();
Show_ALG_Graph(d_graph);
printf("traverse the graph through DFS:\n");
DFS_ALG(d_graph); // 深度优先邻接表有向图
return 0;
}
// 节点表
struct ALG_Graph *Create_ALG_Graph(void)
{
int i, j;
char u, v;
struct ALG_Graph *graph;
graph = (struct ALG_Graph *)malloc(sizeof(struct ALG_Graph));
printf("please enter the number of vex: ");
scanf("%d", &graph->vex_num);
printf("please enter the number of edge: ");
scanf("%d", &graph->edge_num);
while(getchar() != '\n'); // 消灭回车
//节点信息
printf("please enter the vertex:\n");
for(i = 0; i < graph->vex_num; i++)
{
graph->Vex[i].node = getchar();
while(getchar() != '\n');
}
//指针部分设为空
for(i = 0; i < graph->vex_num; i++)
{
graph->Vex[i].first = NULL;
}
// 输入顶点信息
while(graph->edge_num--)
{
printf("please enter the vex that connect each other by edge:\n");
u = getchar();
while(getchar() != '\n');
v = getchar();
while(getchar() != '\n');
i = search_vex(graph, u);
j = search_vex(graph, v);
if(i != -1 && j != -1)
create_adj_node_list(graph, i, j); // 创建邻接点表
else
{
printf("wrong vex, enter again.\n");
graph->edge_num++;
}
}
return graph;
}
// 创建邻接点表(重点)
void create_adj_node_list(struct ALG_Graph *graph, int i, int j)
{
struct AdjNode *s = (struct AdjNode *)malloc(sizeof(struct AdjNode));
s->index = j;
s->next = graph->Vex[i].first;
graph->Vex[i].first = s;
}
// 查找位置
int search_vex(struct ALG_Graph *graph, char c)
{
int i;
for(i = 0; i < graph->vex_num; i++)
{
if(c == graph->Vex[i].node)
return i;
}
return -1;
}
// 显示
void Show_ALG_Graph(struct ALG_Graph *graph)
{
int i;
struct AdjNode *t;
printf("show the ALG Graph:\n");
for(i = 0; i < graph->vex_num; i++)
{
printf("%c: ", graph->Vex[i].node);
t = graph->Vex[i].first;
while(t != NULL)
{
printf("%d ", t->index);
t = t->next;
}
printf("\n");
}
}
// 广度优先邻接表有向图
void DFS_ALG(struct ALG_Graph *graph)
{
int u;
int n;
int i;
struct AdjNode *p;
int visited[MAX] = {0};
for(i = 0; i < graph->vex_num; i++) // 非连通
{
if(visited[i] == 0)
{
printf("%c ", graph->Vex[i].node);
visited[i] = 1;
push(i);
while(!is_empty()) // 栈不为空
{
u = stack[top-1]; // 获取栈顶编号
p = graph->Vex[u].first;
while(p)
{
n = p->index;
if(visited[n] == 0)
{
visited[n] = 1;
push(n);
printf("%c ", graph->Vex[n].node);
p = graph->Vex[n].first;
}
else
p = p->next; // 遇见访问过的跳过
}
pop(); // 遇到空指针出栈
}
}
}
printf("\n");
}
3.插点法(floyd法)
寻找最短路径
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define MAX 100
// 邻接矩阵的图
struct AMG_Graph
{
int vex_num, edge_num; // 顶点个数,边个数
char Vex[MAX]; // 顶点信息(一维数组)
int Edge[MAX][MAX]; // 顶点关系信息 0/1(二维数组)
};
// 函数声明
struct AMG_Graph *Creat_AMG_Graph(void);
void Show_AMG_Graph_dist_p(struct AMG_Graph *graph); // 显示
int search_vex(struct AMG_Graph *graph, char c); // 寻找二维矩阵点
void Floyd(struct AMG_Graph *graph); // 算法
// 两个二维矩阵声明
double dist[MAX][MAX]; // 权重图
int p[MAX][MAX]; // 前驱点图
// 主函数
int main(void)
{
struct AMG_Graph *d_graph; // 有向图指针
char start, end;
int s, e;
d_graph = Creat_AMG_Graph(); // 创建邻接矩阵
Show_AMG_Graph_dist_p(d_graph);
// 寻找最短路径并显示
Floyd(d_graph);
printf("\n\nNow show the shortest distance matrix:\n");
Show_AMG_Graph_dist_p(d_graph);
// 验证寻找点之间最短距离
printf("please enter the start and end point:\n");
scanf("%c %c", &start, &end);
s = search_vex(d_graph, start);
e = search_vex(d_graph, end);
printf("the shortest distance between %c and %c is %.1f.\n", start, end, dist[s][e]);
return 0;
}
// 创建
struct AMG_Graph *Creat_AMG_Graph(void)
{
int i,j;
char u,v;
double l;
struct AMG_Graph *graph;
graph = (struct AMG_Graph *)malloc(sizeof(struct AMG_Graph));
printf("please enter the number of vex: ");
scanf("%d", &graph->vex_num);
printf("please enter the number of edge: ");
scanf("%d", &graph->edge_num);
while(getchar() != '\n'); // 消灭回车
printf("please enter the vertex:\n");
for(i = 0; i < graph->vex_num; i++)
{
graph->Vex[i] = getchar();
while(getchar() != '\n');
}
// 初始化二维数组
for(i = 0; i < graph->vex_num; i++)
{
for(j = 0; j < graph->vex_num; j++)
{
graph->Edge[i][j] = 0;
// 初始化dist[i][j]
if(i == j)
dist[i][j] = 0;
else
dist[i][j] = INFINITY; //无穷大
// 前驱点初始化为-1
p[i][j] = -1;
}
}
// 输入顶点
while(graph->edge_num--)
{
// 输入有关的两点
printf("please enter the vex that connect each other by edge:\n");
u = getchar();
while(getchar() != '\n');
v = getchar();
while(getchar() != '\n');
// 输入两点距离(权重)
printf("please enter the distance between the two vex:\n");
scanf("%lf", &l);
while(getchar() != '\n');
// 查找两点位置数值
i = search_vex(graph, u);
j = search_vex(graph, v);
// 将dist数组填入权重
if(i != -1 && j != -1)
{
graph->Edge[i][j] = 1; // 邻接矩阵
dist[i][j] = l; // 距离
p[i][j] = i; // 前驱
}
else
{
printf("wrong vex, enter again.\n");
graph->edge_num++;
}
}
return graph;
}
// 显示
void Show_AMG_Graph_dist_p(struct AMG_Graph *graph)
{
int i,j;
// 显示顶点
printf("show the vertex:\n");
for(i = 0; i < graph->vex_num; i++)
printf("%c ", graph->Vex[i]);
printf("\n");
//显示邻接矩阵
printf("show the adjacency matrices:\n");
for(i = 0; i < graph->vex_num; i++)
{
for(j = 0; j < graph->vex_num; j++)
printf("%d\t", graph->Edge[i][j]);
printf("\n");
}
// 显示距离权重矩阵
printf("show the distance matrices:\n");
for(i = 0; i < graph->vex_num; i++)
{
for(j = 0; j < graph->vex_num; j++)
printf("%.1f\t", dist[i][j]);
printf("\n");
}
// 显示前驱矩阵
printf("show the pre point matrices:\n");
for(i = 0; i < graph->vex_num; i++)
{
for(j = 0; j < graph->vex_num; j++)
printf("%d\t", p[i][j]);
printf("\n");
}
}
// 查找位置
int search_vex(struct AMG_Graph *graph, char c)
{
int i;
for(i = 0; i < graph->vex_num; i++)
{
if(c == graph->Vex[i])
return i;
}
return -1;
}
// floyd 算法
void Floyd(struct AMG_Graph *graph)
{
int k, i, j;
for(k = 0; k < graph->vex_num; k++) // 大循环a b c d,分别以a b c d 为插入点
{
for(i = 0; i < graph->vex_num; i++)
{
for(j = 0; j < graph->vex_num; j++) // 遍历dist矩阵
{
if(dist[i][j] > dist[i][k] + dist[k][j])
{
dist[i][j] = dist[i][k] + dist[k][j]; // 更新dist
p[i][j] = p[k][j]; // 更新前驱矩阵
}
}
}
}
}