#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;
}
#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();
};
#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;
}
}
#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;//表示不存在
#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);
}
const static char* Parting_line ="-----------------------------------------------------------------";
若不写static会报错说“Parting_line”重定义,加了就好了,或者将这句写成
const char Parting_line[66] ="-----------------------------------------------------------------";
也行
原因不懂.....