#include<iostream>
#include<vector>
#include<queue>
#include<stack>
#define MAX 10001
using namespace std;
enum GraphType{undigraph,digraph,undinetwork,dinetwork};
template <class T>
struct EdgeType//边
{
T head, tail;
int cost;
EdgeType(T h, T t, int c)
{
head = h; tail = t; cost = c;
}
};
template <class T>
struct Edge
{
T adjvex;
int lowcost;
};
template <class T>
class MGraph
{
int vexnum, edgenum;//顶点数、边数
GraphType kind;//图的类型
vector<vector<int>>edges;//邻接矩阵
vector<T>vexs;//顶点表
public:
MGraph(GraphType t, T v[], int vn, int en)//构造函数(图的类型、顶点、顶点数、边数)
{
vexnum = vn;
edgenum = en;
kind = t;
vexs.resize(vexnum);
edges.resize(vexnum);
for (int i = 0; i < vn; i++)
{
vexs[i] = v[i];
}
for (int i = 0; i < vn; i++)
{
edges[i].resize(vexnum);
}
for (int i = 0; i < vn; i++)
{
for (int j = 0; j < vn; j++)
{
if (i == j)
edges[i][j] = 0;
else
edges[i][j] = MAX;//除了环之外的所有边初始化为没有边
}
}
for (int i = 0; i < en; i++)
{
cout << "请输入一条边邻接的两个顶点的序号以及它的权值:" << endl;
int va, vb;
cin >> va >> vb;
int w;//value of weight
cin >> w;
edges[va][vb] = edges[vb][va] = w;//无向网图
}
}
void PrintMGraph()
{
cout << "邻接矩阵为:" << endl;
for (int row = 0; row < vexnum; row++)
{
for (int col = 0; col < vexnum; col++)
{
if (edges[row][col] == MAX)
cout << "∞" << " ";
else
cout << edges[row][col] << " ";
}
cout << endl;
}
}
~MGraph() {}
T GetVexValue(int i)
{
return vexs[i];
}
int GetEdgeValue(int i, int j)
{
return edges[i][j];
}
int VexNum()
{
return vexnum;
}
void DFS(int v, bool* visited)//连通分量的深度优先搜索
{
//cout << "DFS" << endl;
cout <<vexs[v];//访问第v个顶点
visited[v] = true;
for (int i = 0; i < vexnum; i++)
{
if (edges[v][i] != 0 && edges[v][i] != MAX && !visited[i])//有边且没有被访问过
DFS(i, visited);
}
}
void DFSTraverse()//深度优先遍历
{
bool* visited = new bool[vexnum];//辅助数组
for (int v = 0; v < vexnum; v++)
{
visited[v] = false;//全部初始化为false
}
for (int v = 0; v < vexnum; v++)
{
if (!visited[v])
DFS(v, visited);//每次选取一个未被访问的点作为出发点,访问此连通分量
}
cout << endl;
delete[]visited;
}
void BFSTraverse()
{
//cout << "BFS" << endl;
queue<int> q;
bool* visited = new bool[vexnum];
//初始化所有顶点,均未被访问;
for (int i = 0; i < vexnum; i++)
{
visited[i] = false;
}
for (int i = 0; i < vexnum; i++)
{
if (!visited[i])
{
cout << vexs[i];
visited[i] = true;
//访问一个顶点,就将它的后继点放入队列
q.push(i);
while (!q.empty())
{
int u = q.front();
q.pop();
for (int j = 0; j < vexnum; j++)
{
if (edges[u][j] > 0 && edges[u][j] < MAX && !visited[j])
{
cout << vexs[j];
visited[j] = true;
q.push(j);
}
}
}
}
}
delete[]visited;
cout << endl;
}
int MiniNum(Edge<T>* miniedges)//在miniedges中查找V-U中具有最小权值的顶点序号
{
int min = MAX,k=0;
for (int i = 0; i < vexnum; i++)
{
if (miniedges[i].lowcost < min&&miniedges[i].lowcost!=0)
{
min = miniedges[i].lowcost;
k = i;
}
}
//cout << "k=" << k << endl;
return k;
}
void Prim(int v)
{
Edge<T>* miniedges = new Edge<T>[vexnum];
for (int i = 0; i < vexnum; i++)
{
miniedges[i].adjvex = GetVexValue(v);
miniedges[i].lowcost = GetEdgeValue(v,i);
}
miniedges[v].lowcost = 0;
for (int i = 1; i < vexnum; i++)
{
int k = MiniNum(miniedges);//需要编写一个求最小交叉边的函数
cout << miniedges[k].adjvex << "-->" << GetVexValue(k) << endl;
miniedges[k].lowcost = 0;
for (int j = 0; j < vexnum; j++)
{
if (edges[k][j] < miniedges[j].lowcost)
{
miniedges[j].adjvex = vexs[k];
miniedges[j].lowcost = edges[k][j];
}
}
}
delete[]miniedges;
}
void Dijkstra(int v, int path[], int dist[])
{
bool* s = new bool[vexnum];
for (int i = 0; i < vexnum; i++)
{
s[i] = false;
dist[i] = edges[v][i];//初始化所有顶点到源点的路径长度
if (dist[i] < MAX || i == v)
path[i] = v;//源点自己的前驱为自己,初始时与源点有边的点的前驱为原点
else
path[i] = -1;//没有边的情况
}
dist[v] = 0;
s[v] = true;//将原点放入s集合
//以下为源点之外的点加入s集合的情况
for (int i = 1; i < vexnum; i++)
{
int k = v;
int min = MAX;
for (int j = 0; j < vexnum; j++)
{
//cout <<" s["<<j<<"] = " << s[j] << endl;
if (!s[j] && dist[j] < min)//不在集合s中,且到s距离最短
{
//cout << "!" << endl;
k = j;
min = dist[j];
//cout << " min = dist[" << j << "] = " << min << endl;
}
}
s[k] = true; //将k放入集合s中
//以下为放入k之后更新所有不在s中的点到s的最短距离
for (int w = 0; w < vexnum; w++)
{
if (!s[w] && dist[w] > dist[k] + edges[k][w])
{
dist[w] = dist[k] + edges[k][w];
path[w] = k;
//cout << " path[" << w << "] = " << k << endl;
}
}
}
delete []s;
}
};
template <class T>
void PrintPath(MGraph<T>& g, int path[], int dist[], int v)
{
g.Dijkstra(v, path, dist);
cout << "以" << g.GetVexValue(v) << "为源点的图的最短路径为:" << endl;
for (int j = 0; j < g.VexNum(); j++)
{
//cout <<"path[j]="<< path[j] << endl;
int i = j;
if (path[i] == -1)
{
cout << g.GetVexValue(v) << "-->" << g.GetVexValue(i) << "没有最短距离" << endl;
continue;
}
stack<int> s;
s.push(i);
while (path[i] != v)
{
s.push(path[i]);
i = path[i];
}
//s.push(0);
cout << g.GetVexValue(v);
while (!s.empty())
{
cout << " --> " << g.GetVexValue(s.top());
s.pop();
}
cout << " = " << dist[j]<<endl;
}
}
struct EdgeNode//边表
{
int adjvex;//该边的终点;
EdgeNode* nextedge;//指向下一条边的指针
//int weight;
};
template <class T>
struct VexNode
{
T data;//这个点的信息
EdgeNode* firstedge;//指向这个点的边表指针
};
template<class T>
class ALGraph
{
int vexnum, edgenum;
vector<VexNode<T>> adjlist;
GraphType kind;
public:
ALGraph(GraphType t, T vexs[], int vn, int en)
{
EdgeNode* p;
vexnum = vn; edgenum = en;
kind = t;
adjlist.resize(vexnum);
for (int i = 0; i < vexnum; i++)
{
adjlist[i].data = vexs[i];
adjlist[i].firstedge = 0;
}
for (int j = 0; j < edgenum; j++)
{
cout << "请输入一条边邻接的两个顶点的序号:" << endl;
int va, vb;
cin >> va >> vb;
p = new EdgeNode;
p->adjvex = vb;
p->nextedge = adjlist[va].firstedge;//插在表头
adjlist[va].firstedge = p;
p = new EdgeNode;
p->adjvex = va;
p->nextedge = adjlist[vb].firstedge;
adjlist[vb].firstedge = p;
}
}
void PrintALGraph()
{
cout << "邻接表为:" << endl;
for (int i = 0; i < vexnum; i++)
{
cout << adjlist[i].data << " ";
PrintLink(adjlist[i].firstedge);
}
}
void PrintLink(EdgeNode* next) {
while (next != NULL) {
cout << adjlist[next->adjvex].data << " ";
next = next->nextedge;
}
cout << endl;
}
};
int main()
{
int vexnum,edgenum,path[100],dist[100]; char vex[100];
cout << "请输入顶点数:" << endl;
cin >> vexnum;
cout << "请输入各顶点字母:" << endl;
for (int i = 0; i < vexnum; i++)
{
cin >> vex[i];
}
cout << "请输入边数:" << endl;
cin >> edgenum;
MGraph<char> g(undinetwork, vex, vexnum, edgenum);
ALGraph<char> a(undinetwork, vex, vexnum, edgenum);
cout << "-------------------------------" << endl;
cout << "请选择以下操作:" << endl;
cout << "1.打印邻接矩阵、打印邻接表" << endl;
cout << "2.BFS、DFS" << endl;
cout << "3.最小生成树" << endl;
cout << "4.最短路径" << endl;
cout << "0.退出" << endl;
while (1) {
int k = 0;
cin >> k;
switch (k) {
case 1: {
g.PrintMGraph();
a.PrintALGraph();
break;
}
case 2: {
cout << "BFS:";
g.BFSTraverse();
cout << "DFS:";
g.DFSTraverse();
break;
}
case 3: {
cout << "最小生成树为:" << endl;
g.Prim(0);
break;
}
case 4: {
PrintPath(g, path, dist, 0);
break;
}
case 0: {
exit(0);
}
}
}
return 0;
}
图的基本算法(邻接矩阵、邻接表、BFS广度优先搜索、DFS深度优先搜索、prim实现最小生成树、dijkstra实现单源最短路径)利用菜单选择
最新推荐文章于 2024-07-18 23:37:04 发布