一、思路:
和Kruscal类似,先从一个顶点u出发,找u的邻接顶点v,如果(u,v)权值最小且v顶点不在生成树顶点集合中(防止出现回路),则把边(u,v)存到最小生成树中;否则该顶点已经在生成树顶点集合中,舍弃该边,找权值次小的另一条边。然后,从顶点v出发,找下一条不会出现回路的边(v,w)。直到找到n-1条边。
1.假如从顶点A出发,找A的邻接顶点(不在生成树顶点集合中),且权值最小的边,则是(A,B,12),把该边加入到最小生成树中,顶点B加入到生成树顶点集合中;
2.从顶点B出发,找B的邻接顶点(不在生成树顶点集合中),且组成的权值最小的边,则是(B, F, 7),把该边加入到最小生成树中,顶点F加入到生成树顶点集合中;
3.如此重复,直到取了n-1条边,最后结果如下:
二、实现程序:
1.Graph.h:图的头文件
#ifndef Graph_h
#define Graph_h
#include <iostream>
using namespace std;
const int DefaultVertices = 30;
template <class T, class E>
struct Edge { // 边结点的定义
int dest; // 边的另一顶点位置
E cost; // 表上的权值
Edge<T, E> *link; // 下一条边链指针
};
template <class T, class E>
struct Vertex { // 顶点的定义
T data; // 顶点的名字
Edge<T, E> *adj; // 边链表的头指针
};
template <class T, class E>
class Graphlnk {
public:
const E maxWeight = 100000; // 代表无穷大的值(=∞)
Graphlnk(int sz=DefaultVertices); // 构造函数
~Graphlnk(); // 析构函数
void inputGraph(); // 建立邻接表表示的图
void outputGraph(); // 输出图中的所有顶点和边信息
T getValue(int i); // 取位置为i的顶点中的值
E getWeight(int v1, int v2); // 返回边(v1, v2)上的权值
bool insertVertex(const T& vertex); // 插入顶点
bool insertEdge(int v1, int v2, E weight); // 插入边
bool removeVertex(int v); // 删除顶点
bool removeEdge(int v1, int v2); // 删除边
int getFirstNeighbor(int v); // 取顶点v的第一个邻接顶点
int getNextNeighbor(int v,int w); // 取顶点v的邻接顶点w的下一邻接顶点
int getVertexPos(const T vertex); // 给出顶点vertex在图中的位置
int numberOfVertices(); // 当前顶点数
private:
int maxVertices; // 图中最大的顶点数
int numEdges; // 当前边数
int numVertices; // 当前顶点数
Vertex<T, E> * nodeTable; // 顶点表(各边链表的头结点)
};
// 构造函数:建立一个空的邻接表
template <class T, class E>
Graphlnk<T, E>::Graphlnk(int sz) {
maxVertices = sz;
numVertices = 0;
numEdges = 0;
nodeTable = new Vertex<T, E>[maxVertices]; // 创建顶点表数组
if(nodeTable == NULL) {
cerr << "存储空间分配错误!" << endl;
exit(1);
}
for(int i = 0; i < maxVertices; i++)
nodeTable[i].adj = NULL;
}
// 析构函数
template <class T, class