編程進階練習3

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;
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章