普里姆(Prim)算法

/*********************普里姆(Prim)算法******************/
//网类
template<class Type>
class NetGraph
{
private:
    Type vexs[MAX];//顶点表
    int  arc[MAX][MAX];//邻接矩阵
    int numVertexes, numEdges;//当前网中节点、边数量

    int getPosition(Type el);//获取数据el在顶点表中的位置
    Type readType();//外界读取一个数据
public:
    NetGraph();//创建网图
    ~NetGraph(){}//析构函数
    void print();//打印邻接矩阵
    void MiniSpanTree_Prim();//Prim算法生成最小生成树
};
//获取数据el在顶点表中的位置
template<class Type>
int NetGraph<Type>::getPosition(Type el)
{
    int i;
    for (i = 0; i < this->numVertexes; i++)
    {
        if (this->vexs[i] == el)
            return i;
    }
    return -1;
}
//外界读取一个数据
template<class Type>
Type NetGraph<Type>::readType()
{
    Type ch;
    cout << "Input a edge data: ";
    cin >> ch;
    return ch;
}
//创建网图(手动输入)
template<class Type>
NetGraph<Type>::NetGraph()
{
    int i,j;
    Type c1, c2;
    int p1, p2;
    int weight;//用于存储权值
    cout << "Input Vertexes number: ";
    cin >> this->numVertexes;
    cout << "Input Edge number: ";
    cin >> this->numEdges;
    //检测顶点、边输入合法性
    if (this->numVertexes < 1 || this->numEdges<1 || this->numEdges> this->numVertexes*(this->numVertexes - 1))
    {
        cout << "Error input!" << endl;
        return;
    }
    //顶点初始化
    for (i = 0; i < this->numVertexes; i++)
    {
        cout << "Input a Type data" << i + 1 << ": ";
        cin >> this->vexs[i];
    }
    //邻接矩阵初始化
    for (i = 0; i < this->numVertexes; i++)
    {
        for (j = 0; j < this->numVertexes; j++)
        {
            if (i == j)
                this->arc[i][j] = 0;
            else
                this->arc[i][j] = 65535;
        }
    }
    //边初始化
    for (i = 0; i < this->numEdges; i++)
    {
        c1 = readType();
        c2 = readType();

        p1 = getPosition(c1);
        p2 = getPosition(c2);
        if (p1 == -1 || p2 == -1 || p1 == p2)
        {
            cout << "Earror Input!" << endl;
            return;
        }
        cout << "Input a weight value: ";
        cin >> weight;

        this->arc[p1][p2] = weight;
        this->arc[p2][p1] = weight;
    }
}
//打印邻接矩阵
template<class Type>
void NetGraph<Type>::print()
{
    cout << "******************************" << endl;
    cout << "打印邻接矩阵" << endl;
    int i, j;
    for (i = 0; i < this->numVertexes; i++)
    {
        for (j = 0; j < this->numVertexes; j++)
            cout << this->arc[i][j] << '\t';
        cout << endl;
    }
}
//Prim算法生成最小生成树
template<class Type>
void NetGraph<Type>::MiniSpanTree_Prim()
{
    int min, i, j, k;
    int adjvex[MAX];//保存相关顶点下标
    int lowcost[MAX];//保存相关顶点间边的权值

    lowcost[0] = 0;//初始化第一个权值为0,即第一个元素加入生成树
    adjvex[0] = 0;//初始化第一个顶点下表为0

    for (i = 1; i < this->numVertexes; i++)
    {
        lowcost[i] = this->arc[0][i];//将第一个元素与之有关的权值存入数组
        adjvex[i] = 0;//初始化都为第一个元素的下标
    }
    for (i = 0; i < this->numVertexes; i++)
    {
        min = 65535;//初始化最小权值为65535
        j = 1; k = 0;
        while (j < this->numVertexes)
        {
            if (lowcost[j] != 0 && lowcost[j] < min)
            {
                min = lowcost[j];
                k = j;
            }
            j++;
        }
        cout << "(" << adjvex[k] << ", " << k << ") ";
        lowcost[k] = 0;//当前顶点的权值设置为0,表示此顶点已经完成任务
        for (j = 1; j < this->numVertexes; j++)
        {
            if (lowcost[j] != 0 && this->arc[k][j] < lowcost[j])
            {
                lowcost[j] = this->arc[k][j];
                adjvex[j] = k;
            }
        }
    }
}
//测试程序
int main()
{
    NetGraph<char> graph;
    graph.print();
    graph.MiniSpanTree_Prim();
    return 0;
}
### 普里姆算法概述 普里姆算法是一种用于寻找加权连通图中最小生成树的经典算法。该算法通过逐步扩展一棵初始为空的树,最终覆盖所有节点并使得总权重达到最小[^1]。 ### 算法原理 此算法的核心在于维护两个集合:一个是已经加入到当前正在构建的最小生成树中的顶点;另一个则是尚未被纳入考虑范围内的剩余顶点。每次迭代过程中都会从未处理过的邻接边上选取具有最低成本的一条连接至现有部分,从而不断壮大这棵成长中的树形结构直到遍历整个网络为止[^2]。 ### 实现方式 下面给出Python版本的具体实现: ```python import sys def prim(graph): n = len(graph) key = [sys.maxsize]*n parent = [-1]*n mstSet = [False]*n key[0]=0 result=[] for count in range(n-1): u=minKey(key,mstSet,n) mstSet[u]=True for v in range(n): if graph[u][v]>0 and not mstSet[v]and graph[u][v]<key[v]: parent[v]=u key[v]=graph[u][v] for i in range(1, n): result.append((parent[i],i,graph[parent[i]][i])) return result def minKey(key, mstSet,n): min_val=sys.maxsize min_index=-1 for v in range(n): if (not mstSet[v]) and key[v]<min_val: min_val=key[v] min_index=v return min_index ``` 这段代码定义了一个`prim()`函数接收一个表示无向带权图的二维列表作为输入参数,并返回由三元组组成的列表形式的结果,其中每个元素代表一条边及其两端结点编号以及对应的代价值[^4]。 ### 应用场景 在实际生活中有许多地方需要用到此类技术解决问题,比如城市规划部门为了节省电缆铺设费用,在设计电力传输线路布局方案时就可以借助于它来找到最优路径组合;还有电信运营商建设基站之间的微波通信链路同样适用于此种策略以降低整体造价开销等等[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值