C++实现图的深度优先遍历、广度优先遍历、普利姆算法、克鲁斯卡尔算法

  • 相应的算法是基于邻接矩阵实现的
#include <iostream>
#include <numeric>
#include <queue>
#include <vector>
using namespace std;

const int VEX_MAX = 100;
bool visited[VEX_MAX];
int Vset[VEX_MAX];//判断是否有回路

typedef struct Node{
	char* data;
	int vexnum, arcnum;
	int **G;
}*MGraph;

//边
typedef struct Edge{
	int head;
	int tail;
	int lowcost;
}*Edges;

//创建邻接矩阵
MGraph creatGraph()
{
	MGraph graph = new Node;
	int vex, arc;
	cout << "请输入顶点个数和边数:" << endl;
	cin >> vex >> arc;
	graph->vexnum = vex;
	graph->arcnum = arc;
	graph->data = new char[vex];
	cout << "请输入顶点数据:" << endl;
	char data;
	for (int i = 0; i < vex; i++)
	{
		cin >> data;
		graph->data[i] = data;
	}
	cout << "请输入边的起始点及其权重:" << endl;
	graph->G = new int*[vex];
	for (int i = 0; i < vex; i++)
		graph->G[i] = new int[vex];
	for (int i = 0; i < graph->vexnum; i++)
	{
		for (int j = 0; j < graph->vexnum; j++)
		{
			graph->G[i][j] = 0;
		}
	}
	int start, end, weight;
	for (int i = 0; i < arc; i++)
	{
		cin >> start;
		cin >> end;
		cin >> weight;
		graph->G[start - 1][end - 1] = weight;
		graph->G[end - 1][start - 1] = weight;
	}
	return graph;
}

void DFS(MGraph graph, int v)
{
	visited[v] = true;
	cout << graph->data[v] << "->";
	for (int i = 0; i < graph->vexnum; i++)
	{
		if (graph->G[v][i] != 0 && !visited[i])
		{
			DFS(graph, i);
		}
	}
}
//DFS算法
void DFSTraverse(MGraph graph)
{
	for (int i = 0; i < graph->vexnum; i++)
		visited[i] = false;
	for (int i = 0; i < graph->vexnum; i++)
	{
		if (!visited[i])
			DFS(graph, i);
	}
}

//BFS算法
void BFSTraverse(MGraph graph)
{
	queue<int> MyQueue;
	for (int i = 0; i < graph->vexnum; i++)
		visited[i] = false;
	for (int i = 0; i < graph->vexnum; i++)
	{
		if (!visited[i])
		{
			visited[i] = true;
			cout << graph->data[i] << "->";
			MyQueue.push(i);
			while (!MyQueue.empty())
			{
				int v = MyQueue.front();
				MyQueue.pop();
				for (int i = 0; i < graph->vexnum; i++)
				{
					if (graph->G[v][i] != 0 && !visited[i])
					{
						visited[i] = true;
						cout << graph->data[i] << "->";
						MyQueue.push(i);
					}
				}
			}
		}
	}
}

//根据起始点返回位置
int LocateVex(MGraph graph, char data)
{
	for (int i = 0; i < graph->vexnum; i++)
	{
		if (data == graph->data[i])
			return i;
	}
	return -1;
}

//普利姆算法
void PrimAlgorithm(MGraph graph,char data)
{
	int v = LocateVex(graph, data);
	for (int i = 0; i < graph->vexnum; i++)
		visited[i] = false;
	visited[v] = true;
	//h1和h2记录两个顶点的下标
	int h1, h2;
	int minWeight = 10000;
	for (int k = 1; k < graph->vexnum; k++)//总共边数
	{
		//遍历整个图
		for (int i = 0; i < graph->vexnum; i++)
		{
			for (int j = 0; j < graph->vexnum; j++)
			{
				if (visited[i] && !visited[j] && graph->G[i][j] < minWeight && graph->G[i][j]!=0 )
				{
					minWeight = graph->G[i][j];//找到整个图中前面一个顶点被访问后面一个顶点没有被访问且权值最小的
					h1 = i;
					h2 = j;
				}
				
			}
		}
		cout << "从顶点" << graph->data[h1] << "到" << graph->data[h2] << "权值为:" << graph->G[h1][h2] << endl;
		minWeight = 10000;
		visited[h2] = true;
	}
}

//对边进行排序 冒泡排序
void sortEdges(MGraph graph, Edges& edges)
{
	for (int i = 0; i < graph->arcnum - 1; i++)
	{
		for (int j = 0; j < graph->arcnum - 1 - i; j++)
		{
			if (edges[j].lowcost > edges[j + 1].lowcost)
			{
				Edge temp = edges[j];
				edges[j] = edges[j + 1];
				edges[j + 1] = temp;
			}
		}
	}
}
int getEnd(int* vexs, int i)
{
	while (vexs[i] != 0)
		i = vexs[i];
	return i;
}
//克鲁斯卡尔算法
void KruskalAlgorithm(MGraph graph, Edges edges)
{
	int v1, v2;
	int vs1, vs2;
	int count = 0;
	sortEdges(graph, edges);
	for (int i = 0; i < graph->vexnum; i++)
		Vset[i] = i;
	for (int i = 0; i < graph->arcnum; i++)
	{
		v1 = edges[i].head;
		v2 = edges[i].tail;
		//vs1 = getEnd(Vset, v1);//判断是否有回路 如果边的两个顶点都指向同一个终点 则有回路
		//vs2 = getEnd(Vset, v2);
		vs1 = Vset[v1];
		vs2 = Vset[v2];
		if (vs1 != vs2)
		{
			cout << "从顶点" << graph->data[v1] << "到" << graph->data[v2] << "权值为:" << edges[i].lowcost << endl;
			count++;
			if (count == graph->vexnum - 1)
				break;
			//Vset[vs1] = vs2;//边连接之后 更新终点
			for (int j = 0; j < graph->vexnum; j++)
			{
				if (Vset[j] == vs2)
					Vset[j] = vs1;//统一编号
			}
		}
	}
}

//提取边
Edges createEdges(MGraph graph)
{
	Edges edges = new Edge[graph->arcnum];
	int count = 0;
	for (int i = 0; i < graph->vexnum; i++)
	{
		for (int j = i; j < graph->vexnum; j++)
		{
			if (graph->G[i][j] != 0)
			{
				edges[count].head = i;
				edges[count].tail = j;
				edges[count].lowcost = graph->G[i][j];
				count++;
			}
		}
	}
	return edges;
}


//打印边
void printEdges(MGraph graph, Edges edges)
{
	for (int i = 0; i < graph->arcnum; i++)
	{
		cout << edges[i].head << "->" << edges[i].tail << "=" << edges[i].lowcost << endl;
	}
}

//打印图
void printGraph(MGraph graph)
{
	cout << "邻接矩阵为:" << endl;
	for (int i = 0; i < graph->vexnum; i++)
	{
		for (int j = 0; j < graph->vexnum; j++)
		{
			cout << graph->G[i][j] << " ";
		}
		cout << endl;
	}
}

int main()
{
	MGraph graph = creatGraph();
	Edges edges = createEdges(graph);
	cout << "普利姆算法生成最小生成树:" << endl;
	PrimAlgorithm(graph, 'A');
	cout << "-----" << endl;
	cout << "克鲁斯卡尔算法生成最小生成树:" << endl;
	KruskalAlgorithm(graph, edges);
	printGraph(graph);
	cout << "**********************" << endl;
	cout << "深度优先遍历:";
	DFSTraverse(graph);
	cout << endl;
	cout << "广度优先遍历:";
	BFSTraverse(graph);
	cout << endl;
	return 0;
}

测试用例

6 10
A B C D E F
1 2 6
1 3 1
1 4 5
2 3 5
2 5 3
3 4 5
3 5 6
3 6 4
4 6 2
5 6 6

运行截图

运行截图

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值