目录
链式前向星类(包括非递归深度优先遍历、非递归广度优先遍历、求一条包含所有结点的道路、是否有环、两点之间基本路径):
链式前向星类(包括非递归深度优先遍历、非递归广度优先遍历、求一条包含所有结点的道路、是否有环、两点之间基本路径):
(PS:有向图和无向图的区分靠main程序中用户输入来解决,如果是有向图输入中只有边1 4,如果是无向图输入边1 4以及边4 1)
#pragma once
#include <iostream>
#include <queue>
#include <vector>
#include <string>
using namespace std;
//链式前向星
class chain_forward_star
{
private:
//结点数、边数、边序号(从1开始)
int _node_number, _edge_number, _sequence_number;
//前结点最后出现的边序号
int *_end_edge = new int[_node_number+1] ;
//边类
struct Edge
{
//后结点、前结点上一次出现的边序号
int _end_node, _last_edge;
};
//边数组
Edge* _edge = new Edge[_node_number+1];
public:
//构造函数
chain_forward_star(int node_number, int edge_number):
_node_number(node_number),_edge_number(edge_number)
{
for (int x = 0; x < _node_number + 1; x++)
{
_end_edge[x] = -1;
}
_sequence_number = 1;
}
//默认析构函数
~chain_forward_star()
{
delete[] _end_edge;
delete[] _edge;
}
//加边函数(起点,终点)
void add_edge(int start_node, int end_node)
{
_edge[_sequence_number]._end_node = end_node;
_edge[_sequence_number]._last_edge = _end_edge[start_node];
_end_edge[start_node] = _sequence_number;
_sequence_number++;
}
//非递归深度优先遍历(遍历起点)
void non_recursive_depth_first_traversal(int start_node) const
{
//初始化
//建一个end_edge的副本进行使用
int* temp_end_edge = new int[_node_number + 1];
//flag用于避免回路
bool* flag = new bool[_node_number + 1];
for (int x = 0; x < _node_number + 1; x++)
{
flag[x] = false;
temp_end_edge[x] = _end_edge[x];
}
//vector用于回访前面的结点
vector<int> node_vector;
//算法
flag[start_node] = true;
node_vector.push_back(start_node);
cout << start_node << " ";
for (int temp_edge = temp_end_edge[start_node], temp_node = start_node; ; )
{
if (temp_edge == -1)
{
node_vector.pop_back();
if (node_vector.empty())
{
break;
}
temp_node = node_vector.back();
temp_edge = temp_end_edge[temp_node];
continue;
}
temp_end_edge[temp_node] = _edge[temp_edge]._last_edge;
temp_node = _edge[temp_edge]._end_node;
if (flag[temp_node] == true)
{
temp_node = node_vector.back();
temp_edge = temp_end_edge[temp_node];
continue;
}
flag[temp_node] = true;
node_vector.push_back(temp_node);
cout << temp_node << " ";
temp_edge = temp_end_edge[temp_node];
}
//回收内存
delete [] temp_end_edge;
delete [] flag;
}
//非递归广度优先遍历
void non_recursive_breadth_first_traversal(int start_node) const
{
//初始化
queue<int> node_queue;
bool* flag = new bool[_node_number + 1];
for (int x = 0; x < _node_number + 1; x++)
{
flag[x] = false;
}
//算法
flag[start_node] = true;
node_queue.push(start_node);
while (!node_queue.empty())
{
int temp_node = node_queue.front();
node_queue.pop();
cout << temp_node << " ";
for (int temp_edge = _end_edge[temp_node]; temp_edge!=-1;
temp_edge = _edge[temp_edge]._last_edge)
{
int temp_end_node = _edge[temp_edge]._end_node;
if (flag[temp_end_node] == false)
{
node_queue.push(temp_end_node);
flag[temp_end_node] = true;
}
}
}
//回收
delete [] flag;
}
//求一条包含所有结点的回路
//采用类似之前的深度优先遍历算法,每个结点作为开始结点,一直走,找到所求即退出
void all_node_road_search(void)
{
//初始化
int* temp_end_edge = new int[_node_number + 1];
bool* flag = new bool[_node_number + 1];
//算法
for (int start_node = 1; start_node <= _node_number; start_node++)
{
for (int x = 0; x < _node_number + 1; x++)
{
flag[x] = false;
temp_end_edge[x] = _end_edge[x];
}
vector<int> node_vector;
flag[start_node] = true;
node_vector.push_back(start_node);
for (int temp_edge = temp_end_edge[start_node], temp_node = start_node; ; )
{
if (temp_edge == -1)
{
node_vector.pop_back();
if (node_vector.empty())
{
break;
}
temp_node = node_vector.back();
temp_edge = temp_end_edge[temp_node];
continue;
}
temp_end_edge[temp_node] = _edge[temp_edge]._last_edge;
temp_node = _edge[temp_edge]._end_node;
if (flag[temp_node] == true)
{
break;
}
flag[temp_node] = true;
node_vector.push_back(temp_node);
temp_edge = temp_end_edge[temp_node];
}
//这里不一样
if (node_vector.size() == _node_number)
{
cout << "一条包含所有结点的回路如下:";
for (int x = 0; x < _node_number; x++)
{
cout << node_vector[x] << " ";
}
//回收
delete [] temp_end_edge;
delete [] flag;
return;
}
}
cout << "没有找到一条包含所有结点的回路!";
//回收
delete [] temp_end_edge;
delete [] flag;
return;
}
//是否有环
//采用类似之前的深度优先遍历算法,每个结点作为开始结点,遇到重复的即有环,退出函数
void is_ring(void) const
{
//初始化
int* temp_end_edge = new int[_node_number + 1];
bool* flag = new bool[_node_number + 1];
//算法
for (int start_node = 1; start_node <= _node_number; start_node++)
{
for (int x = 0; x < _node_number + 1; x++)
{
flag[x] = false;
temp_end_edge[x] = _end_edge[x];
}
vector<int> node_vector;
flag[start_node] = true;
node_vector.push_back(start_node);
for (int temp_edge = temp_end_edge[start_node], temp_node = start_node; ; )
{
if (temp_edge == -1)
{
node_vector.pop_back();
if (node_vector.empty())
{
break;
}
temp_node = node_vector.back();
temp_edge = temp_end_edge[temp_node];
continue;
}
temp_end_edge[temp_node] = _edge[temp_edge]._last_edge;
temp_node = _edge[temp_edge]._end_node;
if (flag[temp_node] == true)
{
cout<< "有环!" ;
//回收
delete [] temp_end_edge;
delete [] flag;
return;
}
flag[temp_node] = true;
node_vector.push_back(temp_node);
temp_edge = temp_end_edge[temp_node];
}
}
cout << "无环!";
//回收
delete [] temp_end_edge;
delete [] flag;
return;
}
//找两个点之间的基本路径(点不重复的路径,同时边一定也不重复)
void basic_path_between_two_points(int start_node, int end_node)
{
//初始化
int* temp_end_edge = new int[_node_number + 1];
bool* flag = new bool[_node_number + 1];
for (int x = 0; x < _node_number + 1; x++)
{
flag[x] = false;
temp_end_edge[x] = _end_edge[x];
}
vector<int> node_vector;
//算法
flag[start_node] = true;
node_vector.push_back(start_node);
for (int temp_edge = temp_end_edge[start_node], temp_node = start_node; ; )
{
if (temp_node == end_node)
{
cout << start_node << "、" << end_node <<"两点间基本路径如下:";
for (auto x : node_vector)
{
cout << x << " ";
}
//回收
delete [] temp_end_edge;
delete [] flag;
return;
}
if (temp_edge == -1)
{
node_vector.pop_back();
if (node_vector.empty())
{
break;
}
temp_node = node_vector.back();
temp_edge = temp_end_edge[temp_node];
continue;
}
temp_end_edge[temp_node] = _edge[temp_edge]._last_edge;
temp_node = _edge[temp_edge]._end_node;
if (flag[temp_node] == true)
{
temp_node = node_vector.back();
temp_edge = temp_end_edge[temp_node];
continue;
}
flag[temp_node] = true;
node_vector.push_back(temp_node);
temp_edge = temp_end_edge[temp_node];
}
cout << start_node << "、" << end_node << "两点间没有基本路径!";
//回收
delete [] temp_end_edge;
delete [] flag;
return;
}
};
测试程序:
#include <iostream>
#include "chain_forward_star.h"
using namespace std;
//判断边处理函数
bool process_repeat_edge(int* temp_node_list_1, int* temp_node_list_2,
int start_node, int end_node, int length)
{
for (int x = 1; x <= length; x++)
{
if (temp_node_list_1[x] == start_node && temp_node_list_2[x] == end_node)
{
return false;
}
}
return true;
}
int main()
{
cout << "请输入结点数和边数:";
int node_number = 0 , edge_number = 0;
cin >> node_number >> edge_number;
//输入结点数为0时退出
if(node_number == 0)
{
cout << "错误,结点数为0!" << endl;
return 0;
}
if(edge_number == 0)
{
cout << "错误,边数为0!" << endl;
return 0;
}
if(edge_number > node_number * (node_number - 1))
{
cout << "错误,边数大于通过结点推断数目!" << endl;
return 0;
}
//类实例化
chain_forward_star star(node_number, edge_number);
cout << "每排输入一条边的前结点和后结点,结点只能输入数字,从1到结点数:" << endl;
int start_node = -1;
int end_node = -1;
//用于处理重复边
int* temp_node_list_1 = new int[edge_number+1];
int* temp_node_list_2 = new int[edge_number+1];
//加边
for (int x = 1; x <= edge_number; x++)
{
cin >> start_node >> end_node;
//处理输入不正确的边
if(start_node == -1 || end_node == -1 || start_node > node_number || end_node > node_number)
{
cout << "请输入正确格式的边!" << endl;
return 0;
}
//处理重复边
temp_node_list_1[x] = start_node;
temp_node_list_2[x] = end_node;
if(!process_repeat_edge(temp_node_list_1, temp_node_list_2, start_node, end_node, x-1))
{
cout << "错误,出现重复边!" << endl;
return 0;
}
star.add_edge(start_node, end_node);
}
//回收
delete [] temp_node_list_1;
delete [] temp_node_list_2;
cout << endl;
cout << "非递归深度优先遍历:";
star.non_recursive_depth_first_traversal(1);
cout << endl;
cout << "非递归广度优先遍历:";
star.non_recursive_breadth_first_traversal(1);
cout << endl;
star.all_node_road_search();
cout << endl;
star.is_ring();
cout << endl;
cout<<"请输入想要查找基本路径两个结点:";
int node_1 = -1, node_2 = -1;
cin >> node_1 >> node_2;
if(node_1 == -1 || node_2 == -1 || node_1 > node_number || node_2 > node_number)
{
cout << "请输入正确格式的边!" << endl;
return 0;
}
star.basic_path_between_two_points(node_1, node_2);
cout << endl;
return 0;
}
/*
输入示例,第一排是7个点 8条边
7 8
1 2
1 3
1 4
3 7
4 5
4 6
5 6
2 7
*/