先贴出代码,日后发现有可以改进的,再改)欢迎指出错误
edge.h
#ifndef edge_
#define edge_
#include <iostream>
using namespace std;
template <class T>
class edge
{
public:
edge() {
v1 = -1;
v2 = -1;
w = 0;
}
edge(int theV1, int theV2, T theW) {
v1 = theV1;
v2 = theV2;
w = theW;
}
~edge() {};
int vertex1() const {
return v1;
};
int vertex2() const {
return v2;
};
T weight() const {
return w;
}
operator T() const {
return w;
}
void output(ostream& out) const
{// Put the edge into the stream out.
out << "(" << v1 << ", " << v2 << ", " << w << ")";
}
private:
int v1;
int v2;
T w;
};
template <class T>
ostream& operator<<(ostream& out, const edge<T>& x)
{
x.output(out); return out;
}
#endif
graph.h
#ifndef graph_
#define graph_
#include "edge.h"
#include "vertexIterator.h"
template<class T>
class graph
{
public:
virtual ~graph() {}
virtual int numberOfVertices() const = 0;
virtual int numberOfEdges() const = 0;
virtual bool existsEdge(int, int) const = 0;
virtual void insertEdge(edge<T>*) = 0;
virtual bool eraseEdge(int, int) = 0;
virtual int degree(int) const= 0;
virtual int indegree(int) const = 0;
virtual int outdegree(int) const = 0;
virtual bool directed() const = 0;
virtual bool weighted() const = 0;
virtual vertexIterator<T>* iterator(int) = 0;
};
#endif
arrayWDigraph.h
#pragma once
#ifndef arrayWDigraph_
#define arrayWDigraph_
#include "graph.h"
#include "edge.h"
#include"node.h"
#include "vertexIterator.h"
template<class T>//权值的类型
class arrayWDigraph :public graph<T> {
protected:
const T INF = 9999;
//自带
int n; // 顶点个数
int e; // 边的条数
vector<vector<node<T>>> nodes; // 边表
vector<nodelist> mylist; // 顶点表(从1开始)
//判断该结点是否已经被访问:DFS、topo、findpath共用
int* visited; //该顶点是否已被访问(DFS)
//findpath专用
int* path; //储存路径
int length; //路径长度
//dijkstra专用
bool* canreach; //某点是否可达
T* dis; //到某点的最少费用
stack<int>theShortest;
//受保护的函数
void rDFS(int start,int label) { //被DFS调用
visited[start] = label;
auto pointer = iterator(start);
int now;
while ((now = pointer->next()) != 0) {
if (visited[now] == 0)
rDFS(now,label);
}
}
bool rTopologicalOrder(int *in,int *result) {//被topologicalOrder调用
int cnt = 0;
stack<int>zero;//入度为零的结点下标
for (int i = 1; i <= n; i++) {//入度为零的结点入栈
in[i] = mylist[i].indegree;
if (mylist[i].indegree == 0) {
zero.push(i);
visited[i] = 1;
}
}
while (!zero.empty()) {
int temp = zero.top();
zero.pop();
result[cnt++] = temp;
for (int i = 0; i < nodes[temp].size(); i++) {
in[nodes[temp][i].vex]--;
}
for (int i = 1; i <= n; i++) {
if (visited[i] == 0 && in[i] == 0) {
zero.push(i);
visited[i] = 1;
}
}
}
for (int i = 1; i <= n; i++) {
if (visited[i] == 0)return false;
}
return true;
}
bool rfindPath(int start,int end) {//findpath调用
visited[start] = 1;
auto pointer = iterator(start);
int next;
while ((next = pointer->next()) != 0) {
if (visited[next] == 0) {
path[++length] = next;
if (rfindPath(next,end) || next == end) {
return true;
}
length--;
}
}
return false;
}
void rdijkstra(int start) {
int cnt = 1;
for (int i = 1; i <= n - 1; i++) {//更新n-1次
T min = INF;
int minnode = 0;
for (int j = 1; j <= n; j++) {
if (dis[j] < min && visited[j] == 0) {
min = dis[j];
minnode = j;
}
}
if (minnode == 0)continue;//没有可更新的点
//path[minnode] = start;
//没有路径的情况
visited[minnode] = 1;//已找到到达minnode的最短路径
auto pointer = iterator(minnode);
int next, pos;
T weight;
while ((next = pointer->next(weight, pos)) != 0) {
if (visited[next] == 0 && dis[next] > nodes[minnode][pos].weight + dis[minnode]) {
dis[next] = nodes[minnode][pos].weight + dis[minnode];
path[next] = minnode;
}
}
}
}
void sdfs(int start,int label) {
visited[start] = label;
auto pointer = nodes[start].begin();
int now;
while (pointer != nodes[start].end()) {
now = pointer->vex;
if (visited[now] == 0)
rDFS(now,label);
pointer++;
}
}
public:
//构造函数
arrayWDigraph(int numberOfVertices = 0)
{
while (1) {
if (numberOfVertices < 0) {
cout << "请重新输入:" << endl;
cin >> numberOfVertices;
}
else {
break;
}
}
n = numberOfVertices;
e = 0;
visited = new int[n + 1];
mylist=vector<nodelist>(n + 1);
path = NULL;
dis = NULL;
canreach = NULL;
nodes = vector<vector<node<T>>>{ (unsigned int)(n+1),vector<node<T> >() };
if (numberOfVertices == 6) {
string cities[6] = { "北京","杭州","深圳","成都","广州","上海" };
for (int i = 1; i <= n; i++) {
mylist[i].info = cities[i - 1];
}
}
}
//检查点的合法性
bool checkNode(int x) {
if (x>=1 && x<=n)return true;
else {
cout << "警告:点:" << x << " 不合法" << endl;
return false;
}
}
//检查边的合法性
bool ifillegal(int x, int y)const {
if (x < 1 || y < 1 || x > n || y > n || x == y) {
return false;
}
return true;
}
//判断该边是否存在
bool existsEdge(int x, int y) const {
for (int i = 0; i < nodes[x].size(); i++) {
if (nodes[x][i].vex == y) {
return true;
}
}
return false;
};
//插入边
void insertEdge(edge<T>* theEdge)
{
//获取下标以及权值
int v1 = theEdge->vertex1();
int v2 = theEdge->vertex2();
T w = theEdge->weight();
//判断合法性
if (!ifillegal(v1, v2))return;
if (existsEdge(v1, v2)) {
auto position = nodes[v1].begin();
for (int i = 0; i < nodes[v1].size(); i++) {
position=find(nodes[v1].begin(), nodes[v1].end(), v2);
}
position->weight = w;
}
//入度出度加一
mylist[v2].indegree++;
mylist[v1].outdegree++;
//在邻接表中添加该点
node<T> temp(v2, w);
nodes[v1].push_back(temp);
e++;
}
//删除边
bool eraseEdge(int x, int y) {
//判断合法性
if (!ifillegal(x, y))return false;
if (!existsEdge(x, y)) {
return false;
}
for (auto i = nodes[x].begin(); i != nodes[x].end(); i++) {
if (i->vex == y) {
nodes[x].erase(remove(nodes[x].begin(), nodes[x].end(), y), nodes[x].end());
mylist[x].outdegree--;
mylist[y].indegree--;
break;
}
}
return true;
};
//点的个数
int numberOfVertices() const {
return n;
};
//边的条数
int numberOfEdges() const {
return e;
};
//度数
int degree(int x) const {
return indegree(x) + outdegree(x);
};
//入度
int indegree(int x) const {
return mylist[x].indegree;
};
//出度
int outdegree(int x) const {
return mylist[x].outdegree;
};
//有向
bool directed() const { return true; };
//有权
bool weighted() const { return true; };
//迭代器类
class myIterator : public vertexIterator<T> {
public:
myIterator(vector<node<T>>& thelist) {//传入引用,减小开销
newlist = thelist;
size = newlist.size() - 1;//初始化
cur = 0;
}
int next() {//取出当前,指向后一个
if (cur > size)return 0;//终止
int nextVertex = newlist[cur].vex;//取出权值和下标
cur++;//游标后移
return nextVertex;
}
int next(T& theWeight) {
if (cur > size)return 0; //终止
int nextVertex = newlist[cur].vex;//取出权值和下标
theWeight = newlist[cur].weight;
cur++;//游标后移
return nextVertex;
}
int next(T& theWeight,int &pos) {
if (cur > size)return 0; //终止
int nextVertex = newlist[cur].vex;//取出权值和下标
theWeight = newlist[cur].weight;
pos= cur++;//游标后移
return nextVertex;
}
void reset() { cur = 0; }//重置游标
protected:
vector<node<T>> newlist; //边表
int x; //起始点
int cur;//游标
int size; //边表长度
};
//迭代器指针(派生类)
myIterator* iterator(int x) {
if (checkNode(x)) {
return new myIterator(nodes[x]);//为类中传入边表,因为该类无法使用主类中的nodes
}
}
//深度优先搜索
void DFS(int start,int label) {
if (!checkNode(start))return;
fill(visited, visited + n + 1, 0);
rDFS(start,label);
for (int i = 1; i <= n; i++) {
if (visited[n] != 0) {
label++;
rDFS(i, label);
}
}
}
//使用自带迭代器
void dfs(int start,int label) {
if (!checkNode(start))return;
fill(visited, visited + n + 1, 0);
sdfs(start,label);
for (int i = 1; i <= n; i++) {
if (visited[n] != 0) {
label++;
sdfs(i, label);
}
}
}
//拓扑排序
int* topologicalOrder() {
int* in = new int[n + 1](); //暂时声明的入度表,为了不改变原数据
int* result = new int[n ](); //存放结果
fill(visited, visited + n + 1, 0);
if (rTopologicalOrder(in,result)) {
for (int i = 0; i < n; i++) {
cout << result[i] << "->";
}
}
delete[]in;
in = NULL;
return result;
}
//找一条路径
int* findPath(int start,int end) {//进行一些只需无需重复执行的初始化工作
path = new int[n + 1];//返回path的地址,必须新分配一条路径,若用fill,导致所有的路径为同一条
fill(visited, visited + n + 1, 0);
length = 0;//路径长度
path[++length] = start;//第一个点入栈
visited[start] = 1;
if (rfindPath(start,end)||start==end) {
path[0] = length;
return path;
}
else {
delete[]path;//删指针标配
path = NULL;
}
}
//求最短路径长度(具体过程位置)
T* dijkstra(int start, int end) {
dis = new T[n + 1];
fill(dis, dis + n + 1, 9999);
dis[0] = n;//dis存起点到该某点最小距离
dis[start] = 0;
path = new int[n + 1]();
path[start] = start;
fill(visited, visited + n + 1, 0);
visited[start] = 1;
auto pointer = iterator(start);
int next;
T weight;
while ((next = pointer->next(weight)) != 0) {
dis[next] = weight;
path[next] = start;
}
rdijkstra(start);
canreach = new bool[n + 1];
for (int i = 1; i <= n; i++) {
canreach[i] = true;
if (dis[i] == INF)canreach[i] = false;
}
if (canreach[end] == false) return NULL;
stack<int>nothing;
theShortest.swap(nothing);
int cnt = 0;
while (end != start) {
theShortest.push(end);
cnt++;
end = path[end];
}
cout << endl;
dis[0] = cnt;
delete[]canreach;
canreach = NULL;
return dis;
}
/******************************************涉及本项目***********************************************/
//判断城市是否存在
void findif(string start, string end, int& a, int& b) {
auto s1 = find(mylist.begin(), mylist.end(), start);
while (s1 == mylist.end()) {
cout << "城市”" << start << "“不存在," << "请重新搜索" << endl;
cin >> start;
s1 = find(mylist.begin(), mylist.end(), start);
}
auto s2 = find(mylist.begin(), mylist.end(), end);
while (s2 == mylist.end()) {
cout << "城市”" << end << "“不存在," << "请重新搜索" << endl;
cin >> end;
s2 = find(mylist.begin(), mylist.end(), end);
}
a = s1 - mylist.begin();
b = s2 - mylist.begin();
}
//查找航线
void search(string start, string end) {
int num1, num2;
findif(start, end, num1, num2);
T* distance = dijkstra(num1, num2);
if (!distance) {
cout << "抱歉,不存在从" << mylist[num1].info << "到" << mylist[num2].info << "的航班" << endl;
return;
}
T times = distance[0];
cout << "其中:" << mylist[num1].info << "-->";
for (int i = 1; i <= times; i++) {
cout << mylist[theShortest.top()].info<< "(共" << distance[theShortest.top()] << "元)";
if (i != times)cout << "-->";
theShortest.pop();
}
cout << endl;
}
//插入航线
void airline(string start, string end) {
int num1, num2;
findif(start, end, num1, num2);
cout << "请输入航班费用:" << endl;
T fee;
cin >> fee;
while (fee < 0) {
cout << "请重新输入(航班费用大于零):" << endl;
cin >> fee;
}
insertEdge(new edge<T>(num1, num2, fee));
cout << "添加成功!!" << endl;
}
//删除航线
void eraseline(string start, string end) {
int num1, num2;
findif(start, end, num1, num2);
if (eraseEdge(num1, num2)) {
cout << "删除成功!" << endl;
}
else {
cout << "航班不存在或者您输入的格式存在问题" << endl;
}
}
//输出必要的基本信息
void infomation() {
int cnt = 1;
while (cnt < 6) {
if (cnt == 3) {
cout << "*************************最低费用航班查询系统*************************" << endl;
}
else {
cout << "**********************************************************************" << endl;
}
cnt++;
}
cout << "************可搜索的" << n << "个城市包括:";
for (int i = 1; i <= n; i++) {
cout << mylist[i].info << " ";
}
cout << "*******";
cout << endl;
cnt = 0;
while (cnt < 4) {
cout << "**********************************************************************" << endl;
cnt++;
}
}
//选择你想要做的事情
int mode() {
int choose = 0;
cout << " 您想做些什么呢......" << endl;
cout << " 1.添加路线" << endl;
cout << " 2.查找路线" << endl;
cout << " 3.删除路线" << endl;
cout << " 4.测试性能" << endl;
cout << " 5.退出程序" << endl;
cin >> choose;
while (choose > 5 && choose < 1) {
cout << "请重新输入:" << endl;
cin >>choose;
}
return choose;
}
//性能测试
void performCompare() {
//构建完全图
for (int i = 1; i <= 100; i++)
{
for (int j = 1; j <= 100; j++)
{
if (i != j)
insertEdge(new edge<T>(i, j, 100));
}
}
//定制的
clock_t start1, finish1;
int label=1,count1 = 0;
start1 = clock();
do
{
DFS(1, label);
count1++;
} while (((finish1 = clock()) - start1) < 1000);
double x1 = ((double)finish1 - (double)start1) / count1;
//自带的
label = 1;
int n = 0;
clock_t start2, finish2;
int count2 = 0;
start2 = clock();
do
{
dfs(1, label);
count2++;
} while (((finish2=clock() )- start2) < 1000);
double x2 = ((double)finish2 - (double)start2) / count2;
cout << "定制DFS运行时间:" << x1 << endl << "迭代器实现的DFS运行时间:" << x2 << endl;
}
};
#endif
node.h
#ifndef node_
#define node_
#include <bits/stdc++.h>
using namespace std;
template<class T>
class node {
public:
int vex; //该点编号
T weight; //到达该点的权值
node(int thevex, T theweight) {
vex = thevex;
weight = theweight;
}
//重载==,用于eraseEdge中的remove方法
bool operator==(int y) {
if (y == this->vex)return true;
else return false;
}
};
class nodelist {
public:
static int cnt;
int indegree; //顶点入度
int outdegree; //顶点出度
string info; //顶点信息(城市名)
nodelist(int theindegree = 0, string theinfo = "") {
indegree = 0;
outdegree = 0;
indegree = theindegree;
info = theinfo;
}
//重载==,用于search方法
bool operator==(string to) {
if (to== this->info)return true;
else return false;
}
};
#endif
iterator
// abstract class for graph vertex iterator
#ifndef vertexIterator_
#define vertexIterator_
using namespace std;
template<class T>
class vertexIterator
{
public:
virtual ~vertexIterator() {}
virtual int next() = 0;
virtual int next(T&) = 0;
};
#endif
主函数
#include "arrayWDigraph.h"
int main() {
arrayWDigraph<double> a(6); //权值为double型的边
//所需城市:北京 杭州 深圳 成都 广州 上海
a.insertEdge(new edge<double>(1, 2, 240));
a.insertEdge(new edge<double>(4, 2, 350));
a.insertEdge(new edge<double>(6, 4, 260));
a.insertEdge(new edge<double>(5, 6, 160));
a.insertEdge(new edge<double>(6, 5, 100));
a.insertEdge(new edge<double>(1, 5, 300));
a.insertEdge(new edge<double>(2, 3, 240));
a.insertEdge(new edge<double>(4, 3, 250));
int cmd=1;
while (cmd==1) {
system("CLS");
a.infomation();
int dowhat = a.mode();
if (dowhat == 1) {
cout << "请输入起始城市和到达城市(以空格间开):" << endl;
string start, end;
cin >> start >> end;
a.airline(start, end);
}
else if (dowhat == 2) {
cout << "请输入您的出发点和目的地(以空格间开):" << endl;
string start, end;
cin >> start >> end;
a.search(start, end);
}
else if(dowhat==3) {
cout << "请输入删除的出发点和目的地(以空格间开):" << endl;
string start, end;
cin >> start >> end;
a.eraseline(start, end);
}
else if(dowhat==4){
arrayWDigraph<int>g(100);
g.performCompare();
}
else {
exit(1);
}
cout << "Bingo!****************继续查询,请输入1,退出请输入0****************" << endl;
cin >> cmd;
system("CLS");
}
return 0;
}
注意)node.h中用了#include <bits/stdc++.h>(实在是图省事,替换一下也可以 ヽ(✿゚▽゚)ノ)
683





