### **算法基本思想** #### **Prim 算法** Prim 算法是一种贪心策略构建最小生成树的方法。 - **核心思想**: 从任意一个顶点开始,逐步将权值最小的边加入生成树,同时保证生成树不会形成环。 - **步骤**: 1. 初始化一个集合 `MST`,用于存储已包含在生成树中的顶点。 2. 从起始顶点出发,将所有与之相连的边放入一个优先队列(最小堆)。 3. 每次从优先队列中取出权值最小的边,若该边的目标顶点不在 `MST` 中,则将该顶点加入 `MST`,并将与该顶点相连的边加入优先队列。 4. 重复此过程,直到所有顶点都包含在生成树中。 - **时间复杂度**: - 使用邻接矩阵:\( O(V^2) \) 适用于稠密图。 - 使用邻接表+最小堆:\( O(E \log V) \) 适用于稀疏图,其中 \( V \) 是顶点数,\( E \) 是边数。 --- #### **Kruskal 算法** Kruskal 算法是一种基于边的贪心策略构建最小生成树的方法。 - **核心思想**: 按照权值从小到大排序所有边,然后逐步选取不形成环的边,直到构建出最小生成树。 - **步骤**: 1. 将所有边按照权值从小到大排序。 2. 初始化一个并查集,用于判断两个顶点是否属于同一连通分量。 3. 从权值最小的边开始,依次检查该边是否会形成环: - 如果不会形成环(即边的两个顶点不在同一集合中),将该边加入生成树,并合并两个顶点所属的集合。 - 否则,跳过该边。 4. 重复此过程,直到生成树包含 \( V-1 \) 条边。 - **时间复杂度**: - 边排序:\( O(E \log E) \),因为需要对所有边进行排序。 - 并查集操作:近似 \( O(E \log V) \),其中查找和合并操作效率很高(接近常数时间)。 - 总时间复杂度:\( O(E \log E + E \log V) \)。由于 \( E \log E \geq E \log V \),可以简化为 \( O(E \log E) \)。 --- ### **算法比较** | **算法** | **适用场景** | **时间复杂度** | **特点** | |-----------------|-------------------------------|-------------------------|--------------------------------------------------------------------------| | **Prim 算法** | 稠密图,适合用邻接矩阵 | \( O(V^2) \) 或 \( O(E \log V) \) | 基于顶点,逐步扩展生成树;实现相对简单,适合稠密图时直接用邻接矩阵表示。 | | **Kruskal 算法**| 稀疏图,适合用边列表 | \( O(E \log E) \) | 基于边,灵活性更高;需要先排序所有边,适合稀疏图。 | 两种算法在不同场景下都可用,但通常 **Prim 更适合稠密图,Kruskal 更适合稀疏图**。