图的基本算法(邻接矩阵、邻接表、BFS广度优先搜索、DFS深度优先搜索、prim实现最小生成树、dijkstra实现单源最短路径)利用菜单选择

#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;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值