【C++】图的实现深度、广度遍历,普利姆算法,克鲁斯卡尔算法
程序员文章站
2022-03-20 11:39:20
...
根据图的抽象数据类型的定义,使用邻接矩阵或邻接表实现一个图。
图的基本功能:
1、图的建立
3、深度优先遍历图
4、广度优先遍历图
5、使用普里姆算法生成最小生成树
6、使用克鲁斯卡尔算法生成最小生成树
类模板的头文件:
#include<iostream>
using namespace std;
const int MAXSIZE = 10;
const int MAX = 10000;
const int MAX_VEXNUM = 6;//克鲁斯卡算法所用顶点数
const int MAX_EDGE = 9;
enum vertexType{DG,WDG,UDG,WUDG};//有向图,带权有向图,无向图,带权无向图
struct VEdge {//克鲁斯卡算法的边集数组
int fromV;//起始顶点
int endV;//终止顶点
int weight;//边的权值
};
template<class T>
class MGraph {
public:
void Inititalize();//初始化顶点数组和邻接矩阵
void CreateDG();
void CreateWDG();
void CreateUDG();
void CreateWUDG();
MGraph( int vertexnum, vertexType _kind);
//对于无向图的遍历
void DFS(int v);//从v的深度优先遍历
void BFS(int v);//从v的广度优先遍历
//普利姆算法
friend void Prime(MGraph<T>& G);
friend int SelectMin(MGraph<T>& G, int lowcost[]);
//克鲁斯卡算法
friend void GenSortEdge(MGraph<T> &G1, VEdge edgeList[]);//获取边集数组
friend void Kruskal(MGraph<T> &G1, VEdge edgeList[]);//克鲁斯卡算法
private:
T vertex[MAXSIZE];//顶点
int arc[MAXSIZE][MAXSIZE];//矩阵
int vertexNum;//顶点数
int arcNum;//边数或者弧数
vertexType kind;//图的种类
};
void GenSortEdge(MGraph<int> &G1, VEdge edgeList[]) {
int k = 0, i, j;
for(i=0;i<G1.vertexNum;i++)//进行边赋值
for(j=i;j<G1.vertexNum;j++)
if (G1.arc[i][j] != -1&& G1.arc[i][j] != 0) {
edgeList[k].fromV = i;
edgeList[k].endV = j;
edgeList[k].weight = G1.arc[i][j];
k++;
}
int pos = k-1;//初始值为边数
while (pos != 0) {//使用冒泡排序的改进对边进行排序
int bound = pos;
pos = 0;
for (int i = 0; i < bound; i++) {
if (edgeList[i].weight > edgeList[i + 1].weight) {
VEdge temp = edgeList[i];
edgeList[i] = edgeList[i+1];
edgeList[i+1] = temp;
pos = i;
}
}
}
}
void Kruskal(MGraph<int> &G1,VEdge edgeList[]){
cout << "Kuruskal:"<<endl;
int vset[MAX_VEXNUM];
for (int i = 0; i < G1.vertexNum; i++)
vset[i] = i;//初始化vset
int k = 0, j = 0;
while (k < G1.vertexNum - 1) {
int m = edgeList[j].fromV, n = edgeList[j].endV;
int sn1 = vset[m];
int sn2 = vset[n];
if (sn1 != sn2) {
cout << "V" << m << "->V" << n << endl;
k++;
for (int i = 0; i < G1.vertexNum; i++) {
if (vset[i] == sn2)
vset[i] = sn1;//集合中sn2改为sn1
}
}
j++;
}
}
int SelectMin(MGraph<int> &G, int lowcost[]) {
int min = MAX;
int k = 0;
for (int i = 1; i < G.vertexNum; i++) {
if (lowcost[i] != 0 && lowcost[i] < min&&lowcost[i] != -1) {//寻找U——V的最小权值边
min = lowcost[i];
k = i;
}
}
return k;
}
void Prime(MGraph<int>& G) {
cout << "Prime:" << endl;
int adjvex[MAXSIZE];//U集合中的顶点序号
int lowcost[MAXSIZE];//U-V的最小权值边
for (int i = 0; i < G.vertexNum; i++) {//初始化,辅助数组储存所有到Vo的边
adjvex[i] = 0;
lowcost[i] = G.arc[0][i];
}
lowcost[0] = 0;//初始化U={Vo}
for (int i = 1; i < G.vertexNum; i++) {
int k = SelectMin(G, lowcost);
cout << 'V' << adjvex[k] << "->V" << k << endl;
lowcost[k] = 0;
for (int j = 0; j < G.vertexNum; j++) {
if (lowcost[j] == -1) {
lowcost[j] = G.arc[k][j];
adjvex[j] = k;
}
if (lowcost[j] != 0 && G.arc[k][j] < lowcost[j]) {//更新U—V边权值
lowcost[j] = G.arc[k][j];
adjvex[j] = k;
}
}
}
}
bool vistedDFS[MAXSIZE] = { 0 };//顶点的初始状态
template<class T>
void MGraph<T>::DFS(int v) {
cout << vertex[v];
vistedDFS[v] = 1;
for (int j = 0; j < vertexNum; j++)//非连通图
if (arc[v][j] != 0 && vistedDFS[j] == 0)
DFS(j);
}
template<class T>
void MGraph<T>::BFS(int v) {
bool visitedBFS[MAXSIZE] = { 0 };
int queue[MAXSIZE];
int f = 0, r = 0; //构造一个空队列
cout << vertex[v];
visitedBFS[v] = 1;
queue[++r] = v;//V入队
while (f != r) {//队列非空
v = queue[++f];//队头元素出队
for (int j = 0; j < vertexNum; j++) {
if (arc[v][j] !=0 && visitedBFS[j] == 0) {//存在未访问过的临接点
cout << vertex[j];
visitedBFS[j] = 1;
queue[++r] = j;//j入队
}
}
}
}
template<class T>
void MGraph<T>::Inititalize() {
T val;
cout << "Please enter each vertex's keywords:";
for (int i = 0; i < vertexNum; i++) {//初始化顶点数组
cin >> val;
vertex[i] = val;
}
for (int i = 0; i < vertexNum; i++)//初始化邻接矩阵
for (int j = 0; j < vertexNum; j++)
arc[i][j] = 0;
}
template<class T>
void MGraph<T>::CreateDG() {
cout << "Enter the start and end points of each arc to build a DG:" << endl;
int vhead, vtail;
while (cin >> vhead >> vtail) {
arc[vhead][vtail] = 1;
}
}
template<class T>
void MGraph<T>::CreateWDG() {
cout << "Enter the start and end points and weight of each arc to build a WDG:" << endl;
int vhead, vtail, weight;
while (cin >> vhead >> vtail >> weight) {
arc[vhead][vtail] = weight;
}
}
template<class T>
void MGraph<T>::CreateUDG() {
cout << "Enter the start and end points of each arc to build an UDG:" << endl;
int vhead, vtail;
while (cin >> vhead >> vtail) {
arc[vhead][vtail] = 1;
arc[vtail][vhead] = 1;
}
}
template<class T>
void MGraph<T>::CreateWUDG() {
cout << "Enter the start and end points and weight of each arc to build a WUDG:" << endl;
int vhead, vtail, weight;
while (cin >> vhead >> vtail >> weight) {
arc[vhead][vtail] = weight;
arc[vtail][vhead] = weight;
}
}
template<class T>
MGraph<T>::MGraph(int vertexnum, vertexType _kind):vertexNum(vertexnum),arcNum(9),kind(_kind){//构造函数初始化
Inititalize();
switch (kind){
case DG:{
CreateDG(); //构造一个有向图
break;
}
case WDG:{
CreateWDG(); //构造一个带权有向图
break;
}
case UDG:{
CreateUDG(); //构造一个无向图
break;
}
case WUDG:{
CreateWUDG(); //构造一个带权无向图
break;
}
default:
return;
}
//输出矩阵
cout << "Print the adjacency matrix:" << endl;
cout << " ";
for (int i = 0; i < vertexNum; i++)
cout << vertex[i] << " ";
cout << endl;
for (int i = 0; i < vertexNum; i++) {
cout << vertex[i] << ' ';
for (int j = 0; j < vertexNum; j++)
cout << arc[i][j]<<' ';
cout << endl;
}
}
测试函数:
/********************************************************************************************************
1.测试函数每次只能选择一个
2.为测试方便,均采用节点为6的图,BFS和DFS测试选择t1(),最小生成图t2()
3.最小生成图测试参考数据:(未直接连通的边权值为-1)
0 1 46 0 2 19 0 3 34 0 4 -1 0 5 -1 1 2 25 1 3 -1 1 4 17 1 5 -1 2 3 -1 2 4 25 2 5 26 3 4 -1 3 5 12 4 5 38^Z
************************************************************************************************************/
#include "stdafx.h"
#include<iostream>
#include"MGraph.h"
using namespace std;
VEdge edgeList[MAX_EDGE];
void t1() {//测试DFS/BFS
MGraph<int> m1(6, UDG);
cout << "DFS: ";
m1.DFS(0);
cout << endl;
cout << "BFS: ";
m1.BFS(0);
cout << endl;
}
void t2() {//测试普利姆和克鲁斯卡算法
MGraph<int> m1(6, WUDG);
Prime(m1);
GenSortEdge(m1, edgeList);
Kruskal(m1, edgeList);
}
int main(){
int a;
cout << "please enter 1 or 2 to choose your test's kind:";
cin >> a;
if (a == 1)
t1();
else
t2();
return 0;
}
测试结果:
下一篇: nginx实践