1. Dijkstra 最短路径算法
//File name: shortest_path.h
#ifndef _SHORTEST_PATH_H_
#define _SHORTEST_PATH_H_
#include <stdio.h>
#include <stdlib.h>
#define MAX_NUM 20
#define MAX 1000
struct graph {
int nodes_num;
int G[MAX_NUM][MAX_NUM];
};
void init_graph(struct graph* gra);
int read_graph(char* file_name, struct graph* gra, int* S, int* T);
bool is_empty(struct graph* gra);
void print_path(int pred[], int S, int T);
#endif
//File name: shortest_path.cpp
#include "shortest_path.h"
void init_graph(struct graph* gra) { //初始化图
int i = 0;
int j = 0;
gra->nodes_num = 0;
for(i = 0; i < MAX_NUM; i++)
for(j = 0; j < MAX_NUM; j++)
(gra->G)[i][j] = MAX;
}
bool is_empty(struct graph* gra) { //判空
if(gra->nodes_num == 0) return true;
else return false;
}
int read_graph(char* file_name, struct graph* gra, int* S, int* T) { //读取数据
int i = 0;
int j = 0;
FILE* fp = NULL;
if((fp = fopen(file_name, "r")) == NULL) {
printf("Can not open the file!");
exit(-1);
}
fscanf(fp, "%d", &(gra->nodes_num));
fscanf(fp, "%d", S);
fscanf(fp, "%d", T);
while(!feof(fp)) {
fscanf(fp, "%d", &i);
fscanf(fp, "%d", &j);
fscanf(fp, "%d", &((gra->G)[i][j]));
}
fclose(fp);
return 0;
}
void print_path(int pred[], int S, int T) { //打印路径
int i = 0;
int temp = 0;
int path[MAX_NUM] = {0};
path[i] = T;
temp = pred[T];
while(path[i] != S) {
i = i + 1;
path[i] = temp;
temp = pred[temp];
}
printf("The shortest Path from \"%d\" to \"%d\" is: \n", S, T);
while(i >= 0) {
printf("==>%d", path[i]);
i--;
}
}
int main() {
int i = -1;
int S = -1;
int T = -1;
int next = -1;
int current = -1;
int small_dist = -1;
int perm[MAX_NUM] = {0};
int pred[MAX_NUM] = {0};
int distance[MAX_NUM] = {0};
char file_name[50] = "data.txt";
struct graph* gra = NULL;
for(i = 0; i < MAX_NUM; i++) { //初始化pred[]和distance[]
pred[i] = -1;
distance[i] = MAX;
}
gra = (struct graph*) malloc(sizeof(struct graph));
if(gra == NULL) {
printf("Allocation fails!");
exit(-1);
}
init_graph(gra); //初始化图
read_graph(file_name, gra, &S, &T); //读取数据
if(is_empty(gra)) { //检测
printf("The graph is empty!");
exit(-1);
}
if(S < 0 || S >= gra->nodes_num) {
printf("The node \"%d\" does not exit!", S);
exit(-1);
}
if(T < 0 || T >= gra->nodes_num) {
printf("The node \"%d\" does not exit!", T);
exit(-1);
}
if(S == T) {
printf("The node \"%d\" equals node \"%d\" !", S, T);
exit(-1);
}
perm[S] = 1; //预备
distance[S] = 0;
current = S;
while(perm[T] == 0) { //迭代
small_dist = MAX;
for(i = 0; i < gra->nodes_num; i++) {
if(perm[i] == 0) {
if(distance[current] + (gra->G)[current][i] < distance[i]) {
distance[i] = distance[current] + (gra->G)[current][i];
pred[i] = current;
}
if(distance[i] < small_dist) {
small_dist = distance[i];
next = i;
}
}
}
current = next;
perm[current] = 1;
}
printf("The shortest Distance from \"%d\" to \"%d\" is: %d\n", S, T, distance[T]); //输出最短距离
print_path(pred, S, T); //打印最短路径
return 0;
}
2. DFS
//File name: dfs.h
#ifndef _DFS_H_
#define _DFS_H_
#include <stdio.h>
#include <stdlib.h>
struct node_v {
int info;
int flag;
struct node_v* next;
struct node_e* edge;
};
struct node_e {
int info;
struct node_e* next;
struct node_v* vertex;
};
struct node_v* read_graph(char* file_name, struct node_v * graph, int* S, int* v_num);
struct node_v* find_v(struct node_v* graph, int S);
struct node_v* make_vertex(int i);
struct node_e* make_edge(int i);
struct node_v* joint(struct node_v* graph, int S, int T);
void dfs(struct node_v* graph, struct node_v* start);
struct node_v* select(struct node_v* graph);
#endif
//File name: dfs.cpp
#include "dfs.h"
struct node_v* make_vertex(int i) {
//新建顶点节点
struct node_v* p = NULL;
p = (struct node_v*) malloc(sizeof(struct node_v));
if(p == NULL) {
printf("Allocation fails!");
exit(-1);
}
p->edge = NULL;
p->next = NULL;
p->info = i;
p->flag = 0;
return p;
}
struct node_e* make_edge(int i) {
//新建边的节点
struct node_e* p = NULL;
p = (struct node_e*) malloc(sizeof(struct node_e));
if(p == NULL) {
printf("Allocation fails!");
exit(-1);
}
p->vertex = NULL;
p->next = NULL;
p->info = i;
return p;
}
struct node_v* joint(struct node_v* graph, int S, int T) {
//构造一条由S到T的边
struct node_v* p = graph;
struct node_e* q = NULL;
struct node_e* q_pre = NULL;
p = find_v(graph, S); //找到S节点
if(p == NULL) {
printf("Node \"%s\" does not exist!", S);
exit(-1);
}
q_pre = q = p->edge;
while(q != NULL) { //找到S节点的边的末尾
q_pre = q;
q = q->next;
}
q = make_edge(T); //新建一条边 并连上
if(q_pre == NULL) p->edge = q;
else q_pre->next = q;
p = find_v(graph, T); //找到T节点
if(p == NULL) {
printf("Node \"%s\" does not exist!", T);
exit(-1);
}
q->vertex = p;
return graph;
}
struct node_v* find_v(struct node_v* graph, int S) { //找S节点
int flag = 0;
struct node_v* p = graph;
struct node_e* q = NULL;
while(p != NULL) {
if(p->info == S) {
flag = 1;
break;
}
p = p->next;
}
if(flag == 0) return NULL; //没有找到S节点
else return p; //找到S节点
}
struct node_v* read_graph(char* file_name, struct node_v* graph, int* S, int* v_num) { //读取数据
int i = 0;
int j = 0;
FILE* fp = NULL;
struct node_v* p = NULL;
if((fp = fopen(file_name, "r")) == NULL) {
printf("Can not open the file!");
exit(-1);
}
fscanf(fp, "%d", v_num); //读取顶点总数 建立顶点链
for(i = (*v_num) - 1; i >= 0 ; i--) {
p = make_vertex(i);
p->next = graph;
graph = p;
}
fscanf(fp, "%d", S);
while(!feof(fp)) { //建立边的链
fscanf(fp, "%d", &i);
fscanf(fp, "%d", &j);
graph = joint(graph, i, j);
}
fclose(fp);
return graph;
}
void dfs(struct node_v* graph, struct node_v* start) {
struct node_e * ynode = NULL;
printf("%d ", start->info);
start->flag = 1;
ynode = start->edge;
while(ynode != NULL) {
if(ynode->vertex->flag == 0) dfs(graph, ynode->vertex);
ynode = ynode->next;
}
}
struct node_v* select(struct node_v* graph) {
struct node_v * p = graph;
while(p != NULL) {
if(p->flag == 0) return p;
else p = p->next;
}
return NULL;
}
int main() {
int S = -1;
int v_num = 0;
char file_name[50] = "data.txt";
struct node_v* start = NULL;
struct node_v* graph = NULL;
graph = read_graph(file_name, graph, &S, &v_num);
if(graph == NULL) {
printf("The graph is empty!");
exit(-1);
}
start = find_v(graph, S);
if(start == NULL) {
printf("The node does not exist");
exit(-1);
}
while(start != NULL) {
dfs(graph, start);
start = select(graph);
}
return 0;
}
3. BFS
//File name: queue.h
#ifndef _QUEUE_H_
#define _QUEUE_H_
#define MAX 100
#include <stdlib.h>
#include <stdio.h>
struct queue {
int front;
int rear;
int data[MAX];
};
struct queue* create_Q(); //新建队列
void init_Q(struct queue* Q); //初始化队列
bool empty_Q(struct queue Q); //判断队列是否为空
bool full_Q(struct queue Q); //判断队列是否满
struct queue* insert_Q(struct queue* Q, int item); //进队列
struct queue* delete_Q(struct queue* Q, int* item); //出队列
#endif
//File name: queue.cpp
#include "queue.h"
struct queue* create_Q() {
struct queue* q = NULL;
q = (struct queue*) malloc(sizeof(struct queue));
if(q == NULL) {
printf("Allocation fails!");
exit(-1);
}
return q;
}
void init_Q(struct queue* Q) {
int i = 0;
Q->front = 0;
Q->rear = 0;
for(i = 0; i < MAX; i++) (Q->data)[i] = -1;
}
bool empty_Q(struct queue Q) {
if(Q.front == Q.rear) return true;
else return false;
}
bool full_Q(struct queue Q) {
if((Q.front + 1) % MAX == Q.rear) return true;
else return false;
}
struct queue* insert_Q(struct queue* Q, int item) {
if(!full_Q(*Q)) {
Q->rear = (Q->rear + 1) % MAX;
(Q->data)[Q->rear] = item;
}
return Q;
}
struct queue* delete_Q(struct queue* Q, int* item) {
if(!empty_Q(*Q)) {
Q->front = (Q->front + 1) % MAX;
(*item) = (Q->data)[Q->front];
}
return Q;
}
//File name: graph.h
#ifndef _GRAPH_H_
#define _GRAPH_H_
#include <stdio.h>
#include <stdlib.h>
struct node_v { //顶点节点
int info;
int flag;
struct node_v* next;
struct node_e* edge;
};
struct node_e { //边节点
int info;
struct node_e* next;
struct node_v* vertex;
};
struct node_v* make_vertex(int i); //构造顶点节点
struct node_e* make_edge(int i); //构造边节点
struct node_v* read_graph(char* file_name, struct node_v * graph, int* S, int* v_num); //读取图
struct node_v* find_v(struct node_v* graph, int S); //寻找顶点
struct node_v* joint(struct node_v* graph, int S, int T); //构造边
#endif
//File name: graph.cpp
#include "graph.h"
struct node_v* make_vertex(int i) { //新建顶点节点
struct node_v* p = NULL;
p = (struct node_v*) malloc(sizeof(struct node_v));
if(p == NULL) {
printf("Allocation fails!");
exit(-1);
}
p->edge = NULL;
p->next = NULL;
p->info = i;
p->flag = 0;
return p;
}
struct node_e* make_edge(int i) { //新建边节点
struct node_e* p = NULL;
p = (struct node_e*) malloc(sizeof(struct node_e));
if(p == NULL) {
printf("Allocation fails!");
exit(-1);
}
p->vertex = NULL;
p->next = NULL;
p->info = i;
return p;
}
struct node_v* joint(struct node_v* graph, int S, int T) { //构造由S到T的边
struct node_v* p = graph;
struct node_e* q = NULL;
struct node_e* q_pre = NULL;
p = find_v(graph, S); //找到S节点
if(p == NULL) {
printf("Node \"%s\" does not exist!", S);
exit(-1);
}
q_pre = q = p->edge;
while(q != NULL) { //找到S节点的边的末尾
q_pre = q;
q = q->next;
}
q = make_edge(T); //新建一条边 并连上
if(q_pre == NULL) p->edge = q;
else q_pre->next = q;
p = find_v(graph, T); //找到T节点
if(p == NULL) {
printf("Node \"%s\" does not exist!", T);
exit(-1);
}
q->vertex = p;
return graph;
}
struct node_v* find_v(struct node_v* graph, int S) { //找S节点
int flag = 0;
struct node_v* p = graph;
struct node_e* q = NULL;
while(p != NULL) {
if(p->info == S) {
flag = 1;
break;
}
p = p->next;
}
if(flag == 0) return NULL; //没有找到S节点
else return p; //找到S节点
}
struct node_v* read_graph(char* file_name, struct node_v* graph, int* S, int* v_num) { //读取图
int i = 0;
int j = 0;
FILE* fp = NULL;
struct node_v* p = NULL;
if((fp = fopen(file_name, "r")) == NULL) {
printf("Can not open the file!");
exit(-1);
}
fscanf(fp, "%d", v_num); //读取顶点总数 建立顶点链
for(i = (*v_num) - 1; i >= 0 ; i--) {
p = make_vertex(i);
p->next = graph;
graph = p;
}
fscanf(fp, "%d", S);
while(!feof(fp)) { //建立边的链
fscanf(fp, "%d", &i);
fscanf(fp, "%d", &j);
graph = joint(graph, i, j);
}
fclose(fp);
return graph;
}
//File name: bfs.cpp
#include "queue.h"
#include "graph.h"
void bfs(struct node_v* graph, struct node_v* start) {
int x = 0;
struct node_v * xnode = NULL;
struct node_e * ynode = NULL;
struct queue* Q = NULL;
Q = create_Q(); //新建队列并初始化
init_Q(Q);
printf("%d ", start->info); //访问start节点
start->flag = 1;
Q = insert_Q(Q, start->info); //start进队列
while(!empty_Q(*Q)) {
Q = delete_Q(Q, &x); //出队列
xnode = find_v(graph, x);
ynode = xnode->edge; //第一个后继
while(ynode != NULL) {
if(ynode->vertex->flag == 0) {
printf("%d ", ynode->info); //访问节点
ynode->vertex->flag = 1;
Q = insert_Q(Q, ynode->info); //进队列
}
ynode = ynode->next; //下一个后继
}
}
}
struct node_v* select(struct node_v* graph) { //选择开始遍历的节点
struct node_v * p = graph;
while(p != NULL) {
if(p->flag == 0) return p;
else p = p->next;
}
return NULL;
}
int main() {
int S = -1;
int v_num = 0;
char file_name[50] = "data.txt";
struct node_v* start = NULL;
struct node_v* graph = NULL;
graph = read_graph(file_name, graph, &S, &v_num); //读取图
if(graph == NULL) {
printf("The graph is empty!");
exit(-1);
}
start = find_v(graph, S); //初始化开始遍历的节点
if(start == NULL) {
printf("The node does not exist!");
exit(-1);
}
while(start != NULL) {
bfs(graph, start); //bfs
start = select(graph); //重新选择开始遍历的节点
}
return 0;
}