- 概论:
图的定义,是由顶点的有穷非空集合和顶点之间边的集合组成,通常表示为G(V,E),G表示一个图,V是图中顶点集合,E是图中边集合。
在程序中可通过邻接矩阵和邻接表表示,前者是一个二维数组,后者是有链表域的链表来表示,都是表示节点之间的联系。
图中两顶点之间存在路径则表示是连通的,若顶点可以回到出发的顶点则表示存在环或者回路,不存在环则是简单路径,若任意两顶点是连通的,则表示该图是连通图。无向图中连通且n个顶点n-1条边叫做生成树。
最小生成树:在图中,n个顶点用n-1条边把一个连通图连接起来,权值和最小,为最小生成树。
- 算法:
- 克鲁斯卡尔(kruskal)算法
基本思想:将所有顶点之间路径权值,从小到大有序排列,并在程序中优先遍历路径小的顶点,记录不存在环的路径,直至全部循环完毕。
template <typename T>
struct EdgeTree
{
T begin;
T end;
T weight;
};
EdgeTree<int> edge[15];
vector<EdgeTree<int>> minTree(EdgeTree<int> * mTree, int nodeNum, int edgeNum)
{
vector<EdgeTree<int>> resEdge;//存放最小生成树边
vector<int> parent(nodeNum, 0);//存放点之间连接parent[1] = 2表示顶点1、2之间有连接
int begin = 0, end = 0;
for (int i = 0; i < edgeNum; i++)
{
begin = mTree[i].begin;
end = mTree[i].end;
while (parent[begin] > 0)
begin = parent[begin];
while (parent[end] > 0)
end = parent[end];
if (begin != end)
{
parent[begin] = end;
resEdge.push_back(mTree[i]);
}
}
return resEdge;
}
2 普里姆(Prim)算法
基本思想:将顶点之间连接权值存在一个二维数组中,没有连接两个顶点之间为极大值INT_MAX,循环访问所有顶点,如已经得到该顶点与其它顶点连接的最小权值,则将其标记为0,不做重复访问
template <typename T>
struct EdgeTree
{
T begin;
T end;
T weight;
};
vector<EdgeTree<int>> minPrimTree(const vector<vector<int>> &mTree)
{
int len = mTree.size();//顶点个数
vector<EdgeTree<int>> resEdge;
EdgeTree<int> temEdge;
vector<int> minWeight(len, 0);//边权值最小
vector<int> adjevx(len, 0);
for (int i = 1; i < len; i++)
minWeight[i] = mTree[0][i];//初始化为顶点0与其它顶点连接情况
for (int i = 1; i < len; i++)
{
int j = 1, k = 0;//k记录当前顶点i与其它顶点连接最小权值顶点
int minNum = INT_MAX;
while (j < len)
{
if (!minWeight[i] && minNum > minWeight[i])
{
k = j;
minNum = minWeight[i];
}
j++;
}
temEdge.begin = adjevx[k];
temEdge.end = k;
temEdge.weight = minWeight[k];
resEdge.push_back(temEdge);
minWeight[k] = 0;
for (j = 1; j < len; j++)
{
if (!minWeight[j] && mTree[k][j] < minWeight[j])
{
minWeight[j] = minWeight[k][j];//边权更小的值
}
}
}
return resEdge;
}