Prim 普利姆算法-Priority Queue 方法

博客介绍了普利姆算法,提及无向网的最小生成树是图的子集,边数比顶点数少1,边权值和最小且无环。还介绍了Lazy Prim算法,其需用优先队列,以边权值为主元素建最小堆,并给出主要代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

普利姆算法

  1. 最小生成树,Minimum Spanning Tree
    无向网的最小生成树是图的一个子集,在这个子集中,边的数量比顶点数量少1,所有顶点被这些边连接在一起,而且这些边的权值和为最小。值得一提的是,由于最终的结果为树,所以子集中不含有环(cycle).
  2. Lazy Prim 算法
    Lazy Prim算法需要使用优先队列(Priority Queue),队列中的元素为生成边,定义生成边的结构体如下:
typedef struct edge
{
    int from; //start vertex
    int to;   //end vertex
    VRType cost; //weight of cost
}edge;

以边中的权值为Priority Queue的主元素,建立最小堆。

主要代码如下:

typedef edge priority_queue_element;
void mst_prim_lazy(MGraph G, Heap H, int s, edge *mst_edges, int *mst_cost, int (*pf)(priority_queue_element e1, priority_queue_element e2))
{
    int                    i;
    int                    edge_count;
    int                    node_index;
    priority_queue_element arc;

    for(i=0;i<G.vexnum;i++)
    {
        visited[i]=0;
    }
    *mst_cost=0;
    edge_count=0;
    add_edges(G,s,H,pf);

    while(H->size>0 && edge_count!=(G.vexnum-1))
    {
        arc=heap_extract_min(H,pf);
        node_index = arc.to;

        if (!visited[node_index])
        {
            mst_edges[edge_count++]=arc;
            *mst_cost+=arc.cost;
            add_edges(G,node_index,H,pf);
        }
    }

    //need to check if there is MST in the graph
    return;
}

void add_edges(MGraph G,int node_index, Heap H, int (*pf)(priority_queue_element e1, priority_queue_element e2))
{
    int v;
    int w;
    priority_queue_element arc;
    visited[node_index]=1;
    v=node_index;

    for (w = FirstAdjVex(G, G.vexs[v]); w >= 0; w = NextAdjVex(G, G.vexs[v], G.vexs[w]))
    {
        if(!visited[w])
        {
            arc.from=v;
            arc.to=w;
            arc.cost=G.arcs[v][w].adj;
            min_heap_insert(H,arc,pf);
        }
    }
}

int less_than(priority_queue_element e1, priority_queue_element e2)
{
    return (e1.cost<e2.cost);
}

Main 函数如下:

int main(void)
{
    Heap H;
    MGraph G;
    FILE *fp;
    int i;
    int mst_cost=0;
    int s=0;
   

    fp=fopen("UDN.txt","r");
    CreateGraph(&G,fp);
    edge mst_edges[G.vexnum-1];
    init_min_heap(&H, G.arcnum);

    mst_prim_lazy(G,H,s,mst_edges,&mst_cost,less_than);
 
    for(i=0;i<G.vexnum-1;i++)
    {
        printf("-%c-%c-%d-\n", G.vexs[mst_edges[i].from], G.vexs[mst_edges[i].to], mst_edges[i].cost);
    }
    fclose(fp);
    PressEnter;

    return EXIT_SUCCESS;
}
### 使用何种数据结构实现普利姆(Prim)算法 #### 数据结构 为了高效地实现普利姆算法,通常会使用以下几种主要的数据结构: - **优先队列 (Priority Queue)**:用于存储尚未加入生成树的节点及其到当前生成树的距离。这有助于快速找到下一个要加入生成树的节点。 - **邻接矩阵或邻接表**:表示加权无向图。邻接矩阵适合稠密图,而邻接列表则更适合稀疏图。 - **访问标记数组 (Visited Array)**:记录哪些节点已经被纳入生成树中,防止重复处理同一节点。 #### 实现细节 通过上述提到的数据结构组合可以有效地构建最小生成树。具体来说,在每一步迭代过程中,程序会选择距离现有生成树最近的一个未被访问过的节点,并将其连同对应的边一起添加至生成树内;随后更新其他所有不在生成树内的节点到达新加入节点之间的最短路径长度。 对于优先队列的选择上,可以选择基于堆(heap-based)的方式来进行优化,从而使得插入和删除操作的时间复杂度保持较低水平。 以下是Python语言下的代码示例: ```python import heapq def prim(graph, start_vertex): mst = [] visited = set([start_vertex]) edges = [(cost, start_vertex, to) for to, cost in graph[start_vertex].items()] heapq.heapify(edges) while edges: cost, frm, to = heapq.heappop(edges) if to not in visited: visited.add(to) mst.append((frm, to, cost)) for next_to, next_cost in graph[to].items(): if next_to not in visited: heapq.heappush(edges, (next_cost, to, next_to)) return mst if __name__ == "__main__": G = { 'A': {'B': 2,'C': 3}, 'B': {'A': 2,'C': 1,'D': 1,'E': 4}, 'C': {'A': 3,'B': 1,'F': 5}, 'D': {'B': 1,'E': 1}, 'E': {'B': 4,'D': 1,'F': 1}, 'F': {'C': 5,'E': 1} } result = prim(G, "A") print(result) ``` 此段代码实现了普利姆算法并返回由元组组成的列表作为输出,其中每个元组代表了一条属于最小生成树(MST) 的边以及这条边上的权重[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值