随机生成图,dijkstra算法求最短路径,深度、广度优先历遍【待更新其他算法】

graph_node.h (邻接链表节点类):
#pragma once
#include "pre_definition.h"
//代表边的节点
class graph_node {
	int	serial_num;
	int weight;//每条边的权值
public:
	graph_node* next;
	graph_node();
	graph_node(int num, int quanzhi);
	int get_num();
	int get_weight();
	void set_num(int n);
	void set_weight(int q);
};

graph_node.cpp(实现):

#include "graph_node.h"
#include
graph_node::graph_node() {
	serial_num = tan90;
	weight = tan90;
	next = NULL;
}
graph_node::graph_node(int num, int quanzhi) {
	serial_num = num;
	weight = quanzhi;
	next = NULL;
}
int graph_node::get_num() {
	return serial_num;
}
int graph_node::get_weight() {
	return weight;
}
void graph_node::set_num(int n) {
	serial_num = n;
}
void graph_node::set_weight(int q) {
	weight = q;
}


point_node.h(图中节点的类): 

#pragma once
#include "graph_node.h"
//代表图中点的节点
class point_node {
	int data;
public:
	bool is_visited;
	graph_node* link;
	point_node();
	point_node(int number);
	void set_data(int number);
	int get_data();
};


point_node.cpp(实现):

#include "point_node.h"
#include
point_node::point_node() {
	data = tan90;
	is_visited = 0;
	link = NULL;
}
point_node::point_node(int number) {
	data = number;
	is_visited = 0;
	link = NULL;
}
void point_node::set_data(int number) {
	this->data = number;
}
int point_node::get_data() {
	return data;
}

map.h(图类,包括随机生成一个无向图):

#pragma once
#include"point_node.h"
#include 
using namespace std;
class map {
	point_node* points;
	queue pn_q;
	int map_size;
	int **link_matrix;//邻接矩阵
    //----------------------------------深度优先遍历迭代函数------------------------------------
	void deep_first_searching(int i);
	//----------------------------------广度优先遍历迭代函数------------------------------------
	void breadth_first_searching(int i);
	//----------------------------------Dijkstra接口函数----------------------------
	void Dijkstra();
public:
	map();
	~map();
	//将当前map的邻接链表改成矩阵的形式存储
	void to_matrix();
	//输出矩阵
	void print_matrix();
	//随机生成节点
	void random_form();
	//建立i->serial_num的有向连接
	void my_append_link(int i, int serial_num, int weight);
	//随机生成有向图------这个太蠢
	void random_link();
	//随机生成有向图,邻接表按顺序来的,这个才对
	void random_link_order();
	//输出
	void print_map();
	//依照指针删除某个边节点(i点连接到gn指向的节点的边)
	void delete_edge(int i, graph_node* gn);
	//依照数值删除某个边节点(删除从i到seri_num的边)
	void delete_edge(int i, int seri_num);
	//清理多余连接线使之成为单边有向图
	void clear_map();
	//删除该图
	void kill_curr_map();
	//清除所有is_visited标志位
	void refresh();
	//---------------------------------接口函数---------------------------------------
	//参数接受类型为DFS_way和BFS_way以及Dijkstra_way
	void search(int type);
	//---------------------------------接口函数完毕-----------------------------------

	//***********************迪杰斯特拉算法使用的私有变量及函数**********************
	//***********************迪杰斯特拉算法使用的私有变量及函数**********************
	//***********************迪杰斯特拉算法使用的私有变量及函数**********************
	//***********************迪杰斯特拉算法使用的私有变量及函数**********************
	//***********************迪杰斯特拉算法使用的私有变量及函数**********************
private:
	int source;
	int ** S_set;//已经找出最短路径的节点集合,S_set[i]这一行存的是从源节点到i这个点所需经过的点的序号
				 //数据为-1511291时表示后面没有路了,当首个数据为-1511291时表示该行不在这个集合中

	int ** U_set;//待迭代的节点集合
	int *cost;   //cost[i]存放从 source到i的最小代价值
				 //移除一个set中的hang行,即移除某set中以hang为终点的路
	void remove(int **set, int hang);
	//从from_set复制hang行给to_set
	void copy(int **from_set, int **to_set, int from_hang, int to_hang);
	//在set中的hang行最后加一个点i
	void add(int **set, int hang, int i);
	//从U向S移动某行,即移动某个点的路径
	void move_U2S(int hang);
	//判断i这个行是否在集合set内
	bool is_in(int **set, int i);
	//求a数组中,不在集合S的元素的最小值的编号
	int min_not_in_S(int *a);
	//判断一个数字是否存在(跟-1511291比较)
	bool is_exist(int num);
	//判断一个数字是否无穷大(跟1511291比较)
	bool is_infinite(int num);
public:
	void initiate_dijkstra();
	//寻找最短路径函数
	void find_way(int s);
	//输出S_set,用于debug
	void print_S_set();
	//输出U_set,用于debug
	void print_U_set();
	//输出cost表,用于debug
	void print_cost();
	//用于表示最终结果的函数
	void show_result();
};

map.cpp(实现):

#include "map.h"
#include   
#include 
#include 
using namespace std;
//构造函数
map::map() {
	points = NULL;
	map_size = 0;
	link_matrix = NULL;
	srand((unsigned)time(NULL));
}
//析构函数
map::~map() {
	delete points;
}
//----------------------------------深度优先遍历迭代函数------------------------------------
void map::deep_first_searching(int i) {
	graph_node* temp;
	if (!points[i].is_visited) {
		points[i].is_visited = 1;
		cout << setw(3) << i << " : " << points[i].get_data() << endl;
		for (temp = points[i].link; temp != NULL; temp = temp->next) {
			deep_first_searching(temp->get_num());
		}
	}
}
//----------------------------------广度优先遍历迭代函数------------------------------------
void map::breadth_first_searching(int i) {
	graph_node* temp;
	if (!points[i].is_visited) {
		points[i].is_visited = 1;
		cout << setw(3) << i << " : " << points[i].get_data() << endl;
		for (temp = points[i].link; temp != NULL; temp = temp->next) {
			deep_first_searching(temp->get_num());
		}
	}
}
//----------------------------------Dijkstra接口函数----------------------------
void map::Dijkstra() {
	int source_num;
	cout << "输入源节点的编号" << endl;
	cin >> source_num;
	while (source_num >= map_size) {
		cout << "ERROR! Please choose a correct node to start!" << endl;
		cin >> source_num;
	}
	to_matrix();
	find_way(source_num);
	cout << Parting_line << endl;
	show_result();
	cout << Parting_line << endl;
	system("pause");
}
//将当前map的邻接链表改成矩阵的形式存储
void map::to_matrix() {

	if (points == NULL) {
		cout << "ERROR! The map has not been formed!" << endl;
		system("pause");
		return;
	}
	link_matrix = new int*[map_size];
	graph_node*temp = NULL;

	for (int i = 0; i < map_size; i++) {
		link_matrix[i] = new int[map_size];
		for (int j = 0; j < map_size; j++) {
			if (i == j) {
				link_matrix[i][j] = 0;
			}
			else {
				link_matrix[i][j] = MAXNUM;
			}
		}
	}
	for (int i = 0; i < map_size; i++) {
		temp = points[i].link;
		for (; temp != NULL; temp = temp->next) {
			link_matrix[i][temp->get_num()] = temp->get_weight();
		}
	}
	cout << "Matrix transformation finished!" << endl;
}
//输出矩阵
void map::print_matrix() {
	if (points == NULL) {
		cout << "ERROR! The map has not been formed!" << endl;
		system("pause");
		return;
	}
	if (link_matrix == NULL) {
		cout << "the matrix has not been form" << endl;
		system("pause");
		return;
	}
	cout << Parting_line << endl;
	cout << "matrix:" << endl;

	cout << setw(3) << "|";
	for (int j = 0; j < map_size; j++) {
		cout << setw(3) << j;
	}
	cout << endl;
	for (int j = 0; j < map_size + 1; j++) {
		cout << "---";
	}
	cout << endl;
	for (int i = 0; i < map_size; i++) {
		cout << setw(2) << i << '|';
		for (int j = 0; j < map_size; j++) {
			if (link_matrix[i][j] >= MAXNUM) {
				cout << setw(3) << ' ';
			}
			else {
				cout << setw(3) << link_matrix[i][j];
			}
		}
		cout << endl;
	}
	cout << Parting_line << endl;
}
//随机生成节点
void map::random_form() {
	map_size = (rand() % 10) + min_size;
	points = new point_node[map_size];
	for (int i = 0; i < map_size; i++) {
		points[i].set_data(rand() % 1000);
	}
}
//建立i->serial_num的有向连接
void map::my_append_link(int i, int serial_num, int weight) {
	if (points == NULL) {
		cout << "ERROR! The map has not been formed!" << endl;
		system("pause");
		return;
	}
	graph_node* temp = NULL;
	if (points[i].link == NULL) {
		points[i].link = new graph_node(serial_num, weight);
	}
	else {
		for (temp = points[i].link; temp->next != NULL; temp = temp->next);
		temp->next = new graph_node(serial_num, weight);
	}
}
随机生成有向图------这个太蠢
//void map::random_link() {
//	//srand((unsigned)time(NULL));
//	if (points == NULL) {
//		cout << "ERROR!the map is empty!" << endl;
//		system("pause");
//		return;
//	}
//	graph_node* test_repeat = NULL;
//	bool is_ok;//判断随机值是否ok
//	int random_serial;
//	int random_weight;
//	int temp_length;//与之相连节点的个数
//	for (int i = 0; i < map_size; i++) {
//		test_repeat = NULL;
//		temp_length = min_link + rand() % 3;
//		for (int k = 0; k < temp_length; k++) {
//			//产生一个非重复非自己的数字
//			is_ok = 0;
//			while (is_ok == 0) {
//				test_repeat = points[i].link;
//				random_serial = rand() % map_size;
//				is_ok = 1;
//				if (random_serial == i) {//是否指向自己
//					is_ok = 0;
//					continue;
//				}
//				for (; test_repeat != NULL; test_repeat = test_repeat->next) {//是否已经有了
//					if (random_serial == test_repeat->get_num()) {
//						is_ok = 0;
//						break;
//					}
//				}
//			}
//			//连接两个点(无向图)
//			random_weight = rand() % 9 + 1;
//			my_append_link(i, random_serial, random_weight);
//			my_append_link(random_serial, i, random_weight);
//
//		}
//	}
//}
//随机生成有向图,邻接表按顺序来的,这个才对
void map::random_link_order() {
	//srand((unsigned)time(NULL));
	if (points == NULL) {
		cout << "ERROR!the map is empty!" << endl;
		system("pause");
		return;
	}
	graph_node* test_repeat = NULL;
	int random_weight;
	bool is_ok;//判断随机值是否ok
				//int random_serial;
	for (int i = 0; i < map_size; i++) {
		for (int j = 0; j < map_size; j++) {
			if (rand() % 4 == 1 && i != j) {//1/4的概率生成连接 
				is_ok = 1;
				for (test_repeat = points[i].link; test_repeat != NULL; test_repeat = test_repeat->next) {//是否已经有了
					if (j == test_repeat->get_num()) {
						is_ok = 0;
						break;
					}
				}
				if (is_ok == 0) {
					break;
				}
				random_weight = rand() % 9 + 1;
				my_append_link(i, j, random_weight);
				my_append_link(j, i, random_weight);
			}
		}
	}
}
//输出
void map::print_map() {
	if (points == NULL) {
		cout << "ERROR!the map is empty!" << endl;
		system("pause");
		return;
	}
	graph_node* temp = NULL;
	for (int i = 0; i < map_size; i++) {
		cout << setw(3) << i << " : " << setw(3) << points[i].get_data();
		for (temp = points[i].link; temp != NULL; temp = temp->next) {
			cout << " -> " << setw(3) << temp->get_num() << "(" << temp->get_weight() << ")";
		}
		cout << endl;
	}
}
//依照指针删除某个边节点(i点连接到gn指向的节点的边)
void map::delete_edge(int i, graph_node* gn) {
	if (points == NULL) {
		cout << "ERROR! The map has not been formed!" << endl;
		system("pause");
		return;
	}
	graph_node* temp = this->points[i].link;
	if (temp == NULL) {
		cout << "ERROR! There is no node in " << i << endl;
		system("pause");
		return;
	}

	if (temp == gn) {//如果第一个就是要删的
		points[i].link = temp->next;
		delete temp;
		return;
	}
	for (; temp->next != NULL; temp = temp->next) {
		if (temp->next == gn) {
			temp->next = temp->next->next;
			delete gn;
			return;
		}
	}
	cout << "ERROR! Cannot find the target node. ";
}
//依照数值删除某个边节点(删除从i到seri_num的边)
void map::delete_edge(int i, int seri_num) {
	if (points == NULL) {
		cout << "ERROR! The map has not been formed!" << endl;
		system("pause");
		return;
	}
	graph_node* temp = this->points[i].link;
	if (temp == NULL) {
		cout << "ERROR! There is no node in " << i << endl;
		system("pause");
		return;
	}

	if (temp->get_num() == seri_num) {//如果第一个就是要删的
		points[i].link = temp->next;
		delete temp;
		return;
	}
	for (; temp->next != NULL; temp = temp->next) {
		if (temp->next->get_num() == seri_num) {
			graph_node *curr = temp->next;
			temp->next = temp->next->next;
			delete curr;
			return;
		}
	}
	cout << "ERROR! Cannot find the target node. ";
}
//清理多余连接线使之成为单边有向图
void map::clear_map() {
	if (points == NULL) {
		cout << "ERROR! The map has not been formed!" << endl;
		return;
	}
	graph_node * temp = NULL;
	graph_node * curr = NULL;
	for (int i = 0; i < map_size; i++) {
		temp = points[i].link;
		for (; temp != NULL; temp = temp->next) {
			curr = points[temp->get_num()].link;
			for (; curr != NULL; curr = curr->next) {
				if (curr->get_num() == i) {
					delete_edge(temp->get_num(), curr);
					break;
				}
			}
		}
	}

}
//删除该图
void map::kill_curr_map() {
	delete points;
	map_size = 0;
	delete link_matrix;
}
//---------------------------------接口函数---------------------------------------
//参数接受类型为DFS_way和BFS_way
void map::search(int type) {
	if (points == NULL) {
		cout << "ERROR! The map has not been formed!" << endl;
		system("pause");
		return;
	}
	cout << Parting_line << endl;
	switch (type) {
	case 1: {
		cout << "BFS:" << endl;
		int temp;
		graph_node* curr;
		for (int i = 0; inext) {
					pn_q.push(curr->get_num());
				}
			}
			pn_q.pop();
		}
		break;
	}
	case 2:
	{
		cout << "DFS:" << endl;
		for (int i = 0; i < map_size; i++) {//保证在非联通图的情况下也能遍历
			if (!points[i].is_visited) {
				deep_first_searching(i);
			}
		}
		break;
	}
	case 3:
	{
		Dijkstra();
		break;
	}
	}
	cout << Parting_line << endl;
}
//清除所有is_visited标志位
void map::refresh() {
	if (points == NULL) {
		cout << "ERROR! The map has not been formed!" << endl;
		system("pause");
		return;
	}
	for (int i = 0; i < map_size; i++) {
		points[i].is_visited = 0;
	}
}
//***********************迪杰斯特拉算法使用的私有变量及函数**********************
//***********************迪杰斯特拉算法使用的私有变量及函数**********************
//***********************迪杰斯特拉算法使用的私有变量及函数**********************
//***********************迪杰斯特拉算法使用的私有变量及函数**********************
//***********************迪杰斯特拉算法使用的私有变量及函数**********************

void map::remove(int **set, int hang) {
	if (set == NULL) {
		cout << "ERROR!SET IS EMPTY";
		cout << endl;
	}
	for (int i = 0; i < map_size; i++) {
		set[hang][i] = tan90;
	}
}
//从from_set复制hang行给to_set
void map::copy(int **from_set, int **to_set, int from_hang, int to_hang) {
	if (from_set == NULL || to_set == NULL) {
		cout << "ERROR!SET IS EMPTY";
		cout << endl;
	}
	for (int i = 0; i < map_size; i++) {
		to_set[to_hang][i] = from_set[from_hang][i];
	}
}
//在set中的hang行最后加一个点i
void map::add(int **set, int hang, int i) {
	int j;
	for (j = 0; j < map_size; j++) {
		if (set[hang][j] <= tan90) {
			break;
		}
	}
	set[hang][j] = i;
}
//从U向S移动某行,即移动某个点的路径
void map::move_U2S(int hang) {
	copy(U_set, S_set, hang, hang);
	remove(U_set, hang);
}
//判断i这个行是否在集合set内
bool map::is_in(int **set, int i) {
	if (set[i][0] <= tan90) {
		return 0;
	}
	else return 1;
}
//求a数组中,不在集合S的元素的最小值的编号
int map::min_not_in_S(int *a)
{
	int min_seri;
	for (int i = 0; i < map_size; i++) {
		if (!is_in(S_set, i)) {
			min_seri = i;
			break;
		}
	}
	for (int i = 0; i < map_size; i++) {
		if ((!is_in(S_set, i)) && a[i] < a[min_seri]) {
			min_seri = i;
		}
	}
	return min_seri;
}
//判断一个数字是否存在(跟-1511291比较)
bool map::is_exist(int num) {
	if (num > tan90) {
		return 1;
	}
	return 0;
}
//判断一个数字是否无穷大(跟1511291比较)
bool map::is_infinite(int num) {
	if (num > MAXNUM) {
		return 1;
	}
	return 0;
}
void map::initiate_dijkstra() {
	S_set = new int*[map_size];
	U_set = new int*[map_size];
	cost = new int[map_size];
	for (int i = 0; i < map_size; i++) {
		S_set[i] = new int[map_size];
		U_set[i] = new int[map_size];
		if (!is_infinite(link_matrix[source][i])) {//直接相连则cost为权值
			cost[i] = link_matrix[source][i];
		}
		else {
			cost[i] = MAXNUM;
		}
		for (int j = 0; j < map_size; j++) {
			if (i == source) {
				if (j == 0) {
					S_set[i][j] = source;//S集合初始只有一个点
					U_set[i][j] = tan90;//U集合有剩下全部点
				}
				else {
					S_set[i][j] = tan90;//S集合初始只有一个点
					U_set[i][j] = tan90;//U集合有剩下全部点
				}
			}
			else if (j == 0) {
				S_set[i][j] = tan90;//S集合初始只有一个点
				U_set[i][j] = source;//U集合有剩下全部点
			}
			else if (j == 1 && !is_infinite(link_matrix[source][i])) {//两个边有连接
				S_set[i][j] = tan90;//S集合初始只有一个点
				U_set[i][j] = i;//U集合有剩下全部点
			}
		}
	}
}
//寻找最短路径函数
void map::find_way(int s) {
	if (source >= map_size) {
		cout << "ERROR!Cannot find the source node!";
		system("pause");
		return;
	}
	this->source = s;
	initiate_dijkstra();
	bool finish_flag = 0;//完成标志
	int wftf;//等待从u转到s中的行的序号
	int change_teller;//用于判断cost[i]有没有被更新的值
	while (!finish_flag) {
		wftf = min_not_in_S(cost);
		//print_S_set();
		//print_U_set();
		//system("pause");
		move_U2S(wftf);
		//print_S_set();
		//print_U_set();
		for (int i = 0; i < map_size; i++) {
			change_teller = cost[i];
			cost[i] = ((cost[i] < (cost[wftf] + link_matrix[wftf][i])) ? cost[i] : (cost[wftf] + link_matrix[wftf][i]));
			if (change_teller != cost[i]) {//cost[i]被更新!i行路径需要更改
				copy(S_set, U_set, wftf, i);
				add(U_set, i, i);
			}
		}

		finish_flag = 1;
		for (int k = 0; k < map_size; k++) {
			if (U_set[k][0] != tan90) {//只要U集合中还有数据,就继续做
				finish_flag = 0;
				break;
			}
		}
	}


}
//输出S_set,用于debug
void map::print_S_set() {
	if (S_set == NULL) {
		cout << "ERROR!S_set is empty!" << endl;
		system("pause");
		return;
	}
	cout << Parting_line << endl;
	cout << "Dijkstra_S_set:" << endl;
	cout << setw(3) << "|";
	for (int j = 0; j < map_size; j++) {
		cout << setw(3) << j;
	}
	cout << endl;
	for (int j = 0; j < map_size + 1; j++) {
		cout << "---";
	}
	cout << endl;
	for (int i = 0; i < map_size; i++) {
		//if (S_set[i][0] <= tan90) {
		//	continue;
		//}
		cout << setw(2) << i << '|';
		for (int j = 0; j < map_size; j++) {
			if (S_set[i][j] <= tan90) {
				cout << setw(3) << 'x';
			}
			else {
				cout << setw(3) << S_set[i][j];
			}

		}
		cout << endl;
	}
	cout << Parting_line << endl;
}
//输出U_set,用于debug
void map::print_U_set() {
	if (U_set == NULL) {
		cout << "ERROR!U_set is empty!" << endl;
		system("pause");
		return;
	}
	cout << Parting_line << endl;
	cout << "Dijkstra_U_set:" << endl;
	cout << setw(3) << "|";
	for (int j = 0; j < map_size; j++) {
		cout << setw(3) << j;
	}
	cout << endl;
	for (int j = 0; j < map_size + 1; j++) {
		cout << "---";
	}
	cout << endl;
	for (int i = 0; i < map_size; i++) {
		//if (U_set[i][0] <= tan90) {
		//	continue;
		//}
		cout << setw(2) << i << '|';
		for (int j = 0; j < map_size; j++) {
			if (U_set[i][j] <= tan90) {
				cout << setw(3) << 'x';
			}
			else {
				cout << setw(3) << U_set[i][j];
			}

		}
		cout << endl;
	}
	cout << Parting_line << endl;
}
//输出cost表,用于debug
void map::print_cost() {
	if (cost == NULL) {
		cout << "ERROR!Matrix 'cost' is empty!" << endl;
		system("pause");
		return;
	}
	cout << Parting_line << endl;
	cout << "Dijkstra_cost:" << endl;
	cout << setw(4) << "No." << "|cost" << endl << "----------" << endl;
	for (int i = 0; i < map_size; i++) {
		cout << setw(3) << i << " |";
		if (cost[i] >= MAXNUM) {
			cout << "∞" << endl;
		}
		else {
			cout << cost[i] << endl;
		}
	}
	cout << Parting_line << endl;
}
//用于表示最终结果的函数
void map::show_result() {
	int max_lenth = 0;
	for (int i = 0; i < map_size; i++) {
		for (int j = 0; j < map_size; j++) {
			if (is_exist(S_set[i][j])) {
				max_lenth = ((j - 1) > max_lenth) ? (j - 1) : max_lenth;
			}
		}
	}
	cout << "从源节点" << setw(2) << source << "到各节点的路径分别为:" << endl;
	for (int i = 0; i < map_size; i++) {
		cout << setw(2) << source << " To " << setw(2) << i << ": " << setw(2) << source;
		for (int j = 1; j <= max_lenth; j++) {
			if (is_exist(S_set[i][j])) {
				cout << " -> " << setw(2) << S_set[i][j];
			}
			else {
				cout << "      ";
			}
		}
		cout << ";   cost:" << setw(2) << cost[i] << endl;
	}
}


pre_definition.h(预定义的一些东西,可再此修改图的最小规模):
#pragma once
const int min_size = 5;//图的最少节点数
const int min_link = 1;//图中每个节点的最少边数
const static char* Parting_line ="-----------------------------------------------------------------";
const int BFS_way = 1;//用作search函数的形参,代表广度优先算法
const int DFS_way = 2;//用作search函数的形参,代表深度优先算法
const int Dijkstra_way = 3;//用作search函数的形参,代表迪杰斯特拉算法
const int MAXNUM = 1511291;//最大的数字
const int tan90 = -1511291;//表示不存在

main.cpp(主函数):

#include 
#include "map.h"
using namespace std;
void main() {
	map M;
	M.random_form();
	M.random_link_order();
	M.print_map();
	//M.print_matrix();
	M.search(Dijkstra_way);
}


编译过程中出现过问题,就是pre_definition.h文件中的
const static char* Parting_line ="-----------------------------------------------------------------";
若不写static会报错说“Parting_line”重定义,加了就好了,或者将这句写成

const char Parting_line[66] ="-----------------------------------------------------------------";
也行

原因不懂.....


你可能感兴趣的:(机器智能)