//图的深度优先遍历、广度优先遍历
//最小生成树算法:Prim、Kruskal
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <deque>
#include <set>
#define MAXVEX 100 //最大定点个数
#define INFINITY 65535 //无穷大
struct Graph
{
char vertex[MAXVEX];
int arc[MAXVEX][MAXVEX];
int numVertexs, numEdges;
};
struct Edge
{
int begin;
int end;
int weight;
};
struct COMP
{
bool operator()(const Edge &e1, const Edge &e2)
{
return e1.weight < e2.weight;
}
};
int visit[MAXVEX];
void DFS(Graph &G, int i)
{
visit[i] = 1;
std::cout << G.vertex[i] << std::endl;
for(int j = 0; j < G.numVertexs; ++j)
{
if(G.arc[i][j] == 1 && !visit[j])
{
DFS(G, j);
}
}
}
void BFS(Graph &G)
{
std::deque<int> d;
for(int i = 0; i < G.numVertexs; ++i)
{
if(!visit[i])
{
visit[i] = 1;
d.push_back(i);
std::cout << G.vertex[i] << std::endl;
while(!d.empty())
{
int j = d.front();
d.pop_front();
for(int k = 0; k < G.numVertexs; ++k)
{
if(G.arc[j][k] == 1 && !visit[k])
{
visit[k] = 1;
std::cout << G.vertex[k] << std::endl;
d.push_back(k);
}
}
}
}
}
}
//Prim算法生成最小生成树
void MiniSpanTree_Prim(Graph &G)
{
//将图中顶点进行划分成两部分,一部分是生成树,剩余的是图的其余顶点
//首先将起始顶点0加入生成树部分,然后逐步从剩余的图中选择与生成树部分连接权重最小的顶点加入
//直至n个顶点都加入生成树,此时有n-1条边,最小生成树生成
int vertexNum = G.numVertexs;
std::vector<int> flagVec(vertexNum, 0);//标记是否被考察
int size = vertexNum;
std::vector<int> key(vertexNum, INFINITY);
std::vector<int> parent(vertexNum, 0);//标记每个节点的父节点
key[0] = 0;
parent[0] = -1;
while(size > 0)
{
--size;
int start = 0;
int min = INFINITY;
for(int i = 0; i < vertexNum; ++i)
{
if(!flagVec[i] && min > key[i])
{
start = i;
min = key[i];
}
}
flagVec[start] = 1;
for(int i = 0; i < vertexNum; ++i)
{
if(!flagVec[i] && G.arc[start][i] < key[i])
{
key[i] = G.arc[start][i];
parent[i] = start;
}
}
}
for(int i = 1; i < vertexNum; ++i)
{
int j = parent[i];
std::cout << i << ", " << j << " " << G.arc[j][i] << std::endl;
}
}
int Find(std::vector<int> &parent, int i)
{
//最后一个连通节点
while(parent[i] != -1)
{
i = parent[i];
}
return i;
}
int FindSet(std::vector<std::set<int>> &set, int i)
{
for(int j = 0; j < set.size(); ++j)
{
if(set[j].find(i) != set[j].end())
{
return j;
}
}
return -1;
}
void UnionSet(std::vector<std::set<int>> &set, int n, int m)
{
//将集合n和集合m进行合并
for(std::set<int>::iterator it = set[m].begin(); it != set[m].end(); ++it)
{
set[n].insert(*it);
}
std::vector<std::set<int>>::iterator iter = set.begin();
set.erase(iter + m);
}
void MiniSpanTree_Kruskal(Graph &G)
{
std::vector<Edge> edgeVec;
for(int i = 0; i < G.numVertexs; ++i)
{
for(int j = i + 1; j < G.numVertexs; ++j)
{
if(G.arc[i][j] != INFINITY)
{
Edge e;
e.begin = i;
e.end = j;
e.weight = G.arc[i][j];
edgeVec.push_back(e);
}
}
}
std::vector<int> parent(G.numVertexs, -1);//记录各生成树中的节点
std::sort(edgeVec.begin(), edgeVec.end(), COMP());
std::vector<int> flagVec(G.numVertexs, 0);
for(int i = 0; i < G.numEdges; ++i)
{
Edge &e = edgeVec[i];
int start = e.begin;
int end = e.end;
//需要判断start和end是否在同一棵树中,若是,则舍弃这条边;否则,将这两棵树连在一起
int n = Find(parent,start);
int m = Find(parent, end);
if(n != m)
{
//将这两个连通分支进行合并
parent[n] = m;
std::cout << start << "," << end << " " << G.arc[start][end] << std::endl;
}
}
std::vector<std::set<int>> set;
for(int i = 0; i < G.numEdges; ++i)
{
Edge &e = edgeVec[i];
int n = FindSet(set, e.begin);//查找e.begin属于的集合
int m = FindSet(set, e.end);
if(n != m)
{
//n和m没有在同一个集合中,进行合并
std::cout << e.begin << "," << e.end << " " << e.weight << std::endl;
if(n != -1 && m == -1)
{
//将e.end插入到n集合中
set[n].insert(e.end);
}
else if(n == -1 && m != -1)
{
//将e.begin插入到m集合中
set[m].insert(e.begin);
}
else if(n == -1 && m == -1)
{
//新增集合
std::set<int> tmp;
tmp.insert(e.begin);
tmp.insert(e.end);
set.push_back(tmp);
}
else if(n != -1 && m != -1)
{
//将集合n和集合m进行合并
UnionSet(set, n, m);
}
}
}
}
int main(int nArgs, char* pArg[])
{
Graph G;
G.numVertexs = 9;
G.numEdges = 15;
for(int i = 0; i < G.numVertexs; ++i)
{
G.vertex[i] = i;
}
for(int i = 0; i < G.numVertexs; ++i)
{
for(int j = 0; j < G.numVertexs; ++j)
{
G.arc[i][j] = INFINITY;
}
}
G.arc[0][1] = G.arc[1][0] = 10;
G.arc[0][5] = G.arc[5][0] = 11;
G.arc[1][2] = G.arc[2][1] = 18;
G.arc[1][6] = G.arc[6][1] = 16;
G.arc[1][8] = G.arc[8][1] = 12;
G.arc[2][3] = G.arc[3][2] = 22;
G.arc[2][8] = G.arc[8][2] = 8;
G.arc[3][4] = G.arc[4][3] = 20;
G.arc[3][6] = G.arc[6][3] = 24;
G.arc[3][7] = G.arc[7][3] = 16;
G.arc[3][8] = G.arc[8][3] = 21;
G.arc[4][5] = G.arc[5][4] = 26;
G.arc[4][7] = G.arc[7][4] = 7;
G.arc[5][6] = G.arc[6][5] = 17;
G.arc[6][7] = G.arc[7][6] = 19;
//MiniSpanTree_Prim(G);
MiniSpanTree_Kruskal(G);
system("pause");
return 0;
}
//最小生成树算法:Prim、Kruskal
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <deque>
#include <set>
#define MAXVEX 100 //最大定点个数
#define INFINITY 65535 //无穷大
struct Graph
{
char vertex[MAXVEX];
int arc[MAXVEX][MAXVEX];
int numVertexs, numEdges;
};
struct Edge
{
int begin;
int end;
int weight;
};
struct COMP
{
bool operator()(const Edge &e1, const Edge &e2)
{
return e1.weight < e2.weight;
}
};
int visit[MAXVEX];
void DFS(Graph &G, int i)
{
visit[i] = 1;
std::cout << G.vertex[i] << std::endl;
for(int j = 0; j < G.numVertexs; ++j)
{
if(G.arc[i][j] == 1 && !visit[j])
{
DFS(G, j);
}
}
}
void BFS(Graph &G)
{
std::deque<int> d;
for(int i = 0; i < G.numVertexs; ++i)
{
if(!visit[i])
{
visit[i] = 1;
d.push_back(i);
std::cout << G.vertex[i] << std::endl;
while(!d.empty())
{
int j = d.front();
d.pop_front();
for(int k = 0; k < G.numVertexs; ++k)
{
if(G.arc[j][k] == 1 && !visit[k])
{
visit[k] = 1;
std::cout << G.vertex[k] << std::endl;
d.push_back(k);
}
}
}
}
}
}
//Prim算法生成最小生成树
void MiniSpanTree_Prim(Graph &G)
{
//将图中顶点进行划分成两部分,一部分是生成树,剩余的是图的其余顶点
//首先将起始顶点0加入生成树部分,然后逐步从剩余的图中选择与生成树部分连接权重最小的顶点加入
//直至n个顶点都加入生成树,此时有n-1条边,最小生成树生成
int vertexNum = G.numVertexs;
std::vector<int> flagVec(vertexNum, 0);//标记是否被考察
int size = vertexNum;
std::vector<int> key(vertexNum, INFINITY);
std::vector<int> parent(vertexNum, 0);//标记每个节点的父节点
key[0] = 0;
parent[0] = -1;
while(size > 0)
{
--size;
int start = 0;
int min = INFINITY;
for(int i = 0; i < vertexNum; ++i)
{
if(!flagVec[i] && min > key[i])
{
start = i;
min = key[i];
}
}
flagVec[start] = 1;
for(int i = 0; i < vertexNum; ++i)
{
if(!flagVec[i] && G.arc[start][i] < key[i])
{
key[i] = G.arc[start][i];
parent[i] = start;
}
}
}
for(int i = 1; i < vertexNum; ++i)
{
int j = parent[i];
std::cout << i << ", " << j << " " << G.arc[j][i] << std::endl;
}
}
int Find(std::vector<int> &parent, int i)
{
//最后一个连通节点
while(parent[i] != -1)
{
i = parent[i];
}
return i;
}
int FindSet(std::vector<std::set<int>> &set, int i)
{
for(int j = 0; j < set.size(); ++j)
{
if(set[j].find(i) != set[j].end())
{
return j;
}
}
return -1;
}
void UnionSet(std::vector<std::set<int>> &set, int n, int m)
{
//将集合n和集合m进行合并
for(std::set<int>::iterator it = set[m].begin(); it != set[m].end(); ++it)
{
set[n].insert(*it);
}
std::vector<std::set<int>>::iterator iter = set.begin();
set.erase(iter + m);
}
void MiniSpanTree_Kruskal(Graph &G)
{
std::vector<Edge> edgeVec;
for(int i = 0; i < G.numVertexs; ++i)
{
for(int j = i + 1; j < G.numVertexs; ++j)
{
if(G.arc[i][j] != INFINITY)
{
Edge e;
e.begin = i;
e.end = j;
e.weight = G.arc[i][j];
edgeVec.push_back(e);
}
}
}
std::vector<int> parent(G.numVertexs, -1);//记录各生成树中的节点
std::sort(edgeVec.begin(), edgeVec.end(), COMP());
std::vector<int> flagVec(G.numVertexs, 0);
for(int i = 0; i < G.numEdges; ++i)
{
Edge &e = edgeVec[i];
int start = e.begin;
int end = e.end;
//需要判断start和end是否在同一棵树中,若是,则舍弃这条边;否则,将这两棵树连在一起
int n = Find(parent,start);
int m = Find(parent, end);
if(n != m)
{
//将这两个连通分支进行合并
parent[n] = m;
std::cout << start << "," << end << " " << G.arc[start][end] << std::endl;
}
}
std::vector<std::set<int>> set;
for(int i = 0; i < G.numEdges; ++i)
{
Edge &e = edgeVec[i];
int n = FindSet(set, e.begin);//查找e.begin属于的集合
int m = FindSet(set, e.end);
if(n != m)
{
//n和m没有在同一个集合中,进行合并
std::cout << e.begin << "," << e.end << " " << e.weight << std::endl;
if(n != -1 && m == -1)
{
//将e.end插入到n集合中
set[n].insert(e.end);
}
else if(n == -1 && m != -1)
{
//将e.begin插入到m集合中
set[m].insert(e.begin);
}
else if(n == -1 && m == -1)
{
//新增集合
std::set<int> tmp;
tmp.insert(e.begin);
tmp.insert(e.end);
set.push_back(tmp);
}
else if(n != -1 && m != -1)
{
//将集合n和集合m进行合并
UnionSet(set, n, m);
}
}
}
}
int main(int nArgs, char* pArg[])
{
Graph G;
G.numVertexs = 9;
G.numEdges = 15;
for(int i = 0; i < G.numVertexs; ++i)
{
G.vertex[i] = i;
}
for(int i = 0; i < G.numVertexs; ++i)
{
for(int j = 0; j < G.numVertexs; ++j)
{
G.arc[i][j] = INFINITY;
}
}
G.arc[0][1] = G.arc[1][0] = 10;
G.arc[0][5] = G.arc[5][0] = 11;
G.arc[1][2] = G.arc[2][1] = 18;
G.arc[1][6] = G.arc[6][1] = 16;
G.arc[1][8] = G.arc[8][1] = 12;
G.arc[2][3] = G.arc[3][2] = 22;
G.arc[2][8] = G.arc[8][2] = 8;
G.arc[3][4] = G.arc[4][3] = 20;
G.arc[3][6] = G.arc[6][3] = 24;
G.arc[3][7] = G.arc[7][3] = 16;
G.arc[3][8] = G.arc[8][3] = 21;
G.arc[4][5] = G.arc[5][4] = 26;
G.arc[4][7] = G.arc[7][4] = 7;
G.arc[5][6] = G.arc[6][5] = 17;
G.arc[6][7] = G.arc[7][6] = 19;
//MiniSpanTree_Prim(G);
MiniSpanTree_Kruskal(G);
system("pause");
return 0;
}