普里姆算法(Prim)邻接矩阵法
算法代码
C#代码
using System;
namespace Prim
{
class Program
{
static void Main(string[] args)
{
int numberOfVertexes = 9,
infinity = int.MaxValue;
int[][] graph = new int[][] {
new int[]{0, 10, infinity, infinity, infinity, 11, infinity, infinity, infinity },
new int[]{ 10, 0, 18, infinity, infinity, infinity, 16, infinity, 12 },
new int[]{ infinity, 18, 0, 22, infinity, infinity, infinity, infinity, 8 },
new int[]{ infinity, infinity, 22, 0, 20, infinity, 24, 16, 21 },
new int[]{ infinity, infinity, infinity, 20, 0, 26, infinity, 7, infinity },
new int[]{ 11, infinity, infinity, infinity, 26, 0, 17, infinity, infinity },
new int[]{ infinity, 16, infinity, 24, infinity, 17, 0, 19, infinity },
new int[]{ infinity, infinity, infinity, 16, 7, infinity, 19, 0, infinity },
new int[]{ infinity, 12, 8, 21, infinity, infinity, infinity, infinity, 0 },
};
//Prim(graph, numberOfVertexes);
PrimSimplified(graph, numberOfVertexes);
}
static void Prim(int[][] graph, int numberOfVertexes)
{
bool debug = true;
int[] adjVex = new int[numberOfVertexes], // 邻接顶点数组:搜索边的最小权值过程中各边的起点坐标
lowCost = new int[numberOfVertexes]; // 各边权值数组:搜索边的最小权值过程中各边的权值,数组下标为边的终点。
for (int i = 0; i < numberOfVertexes; i++) // 从图G的下标为0的顶点开始搜索。(也是图G的最小生成树的顶点集合)。
{
adjVex[i] = 0;
}
for (int i = 0; i < numberOfVertexes; i++) // 初始从下标为0的顶点开始到下标为i的顶点的边的权值去搜索。找lowCost中权值最小的下标i。
{
lowCost[i] = graph[0][i];
}
int k = 0; // 初始假定权值最小的边的终点的下标为k。
for (int i = 1; i < numberOfVertexes; i++)
{
if (debug)
{
Console.WriteLine($"Loop {i}");
Console.Write("lowCost: ");
PrintArray(lowCost);
Console.Write(" adjVex: ");
PrintArray(adjVex);
Console.WriteLine();
}
int minimumWeight = int.MaxValue; // 搜索过程中发现到的最小的权值。初始设置为最大的整数值以示两点间无边。
for (int j = 1; j < numberOfVertexes; j++)
{
if (lowCost[j] != 0 && lowCost[j] < minimumWeight) // lowCost中0表示该点已经搜索过了。lowCost[j] < minimumWeight即发现目前最小权值。
{
minimumWeight = lowCost[j]; // 发现目前最小权值。
k = j; // 目前最小权值的边的终点下标。
}
}
if (!debug)
{
Console.WriteLine($"({adjVex[k]}, {k})"); // 输出边
}
adjVex[i] = k; // 此时找到的k值即是权值最小的边的终点。将V[k]放入集合U。(这步可省略,因lowCost[j]已被标为“无需搜索”了)。
lowCost[k] = 0; // 0表示该点已经搜索过了,已不需要再被搜索了。
for (int j = 1; j < numberOfVertexes; j++) // 转到以V[k]为开始顶点的边,去与前面u为起始顶点到V[i]为终止顶点的边的权值去比较。
{
if (lowCost[j] != 0 && graph[k][j] < lowCost[j]) // lowCost中0表示该点已经搜索过了。graph[k][j] < lowCost[j]即发现更小权值。
{
lowCost[j] = graph[k][j]; // 更新权值;索引j即终点下标。
adjVex[j] = k; // 下次寻找权值小的边时,从k为下标的顶点为起点。
}
}
if (debug)
{
Console.Write("lowCost: ");
PrintArray(lowCost);
Console.Write(" adjVex: ");
PrintArray(adjVex);
Console.WriteLine();
}
}
}
static void PrimSimplified(int[][] graph, int numberOfVertexes)
{
int[] adjVex = new int[numberOfVertexes], // 邻接顶点数组:搜索边的最小权值过程中各边的起点坐标
lowCost = new int[numberOfVertexes]; // 各边权值数组:搜索边的最小权值过程中各边的权值,数组下标为边的终点。
for (int i = 0; i < numberOfVertexes; i++)
{
adjVex[i] = 0; // 从图G的下标为0的顶点开始搜索。(也是图G的最小生成树的顶点集合)。
lowCost[i] = graph[0][i]; // 初始从下标为0的顶点开始到下标为i的顶点的边的权值去搜索。找lowCost中权值最小的下标i。
}
int k = 0; // 初始假定权值最小的边的终点的下标为k。
for (int i = 1; i < numberOfVertexes; i++)
{
int minimumWeight = int.MaxValue; // 搜索过程中发现到的最小的权值。初始设置为最大的整数值以示两点间无边。
for (int j = 1; j < numberOfVertexes; j++)
{
if (lowCost[j] != 0 && lowCost[j] < minimumWeight) // lowCost中0表示该点已经搜索过了。lowCost[j] < minimumWeight即发现目前最小权值。
{
minimumWeight = lowCost[j]; // 发现目前最小权值。
k = j; // 目前最小权值的边的终点下标。
}
}
Console.WriteLine($"({adjVex[k]}, {k})"); // 输出边
lowCost[k] = 0; // 0表示该点已经搜索过了,已不需要再被搜索了。
for (int j = 1; j < numberOfVertexes; j++) // 转到以V[k]为开始顶点的边,去与前面u为起始顶点到V[i]为终止顶点的边的权值去比较。
{
if (lowCost[j] != 0 && graph[k][j] < lowCost[j]) // lowCost中0表示该点已经搜索过了。graph[k][j] < lowCost[j]即发现更小权值。
{
lowCost[j] = graph[k][j]; // 更新权值;索引j即终点下标。
adjVex[j] = k; // 下次寻找权值小的边时,从k为下标的顶点为起点。
}
}
}
}
static void PrintArray(int[] array)
{
Console.Write("[ ");
for (int i = 0; i < array.Length - 1; i++) // 输出数组的前面n-1个
{
Console.Write($"{ToInfinity(array[i])}, ");
}
if (array.Length > 0) // 输出数组的最后1个
{
int n = array.Length - 1;
Console.Write($"{ToInfinity(array[n])}");
}
Console.WriteLine(" ]");
}
static string ToInfinity(int i) => i == int.MaxValue ? "∞" : i.ToString();
}
}
TypeScript代码
function prim(graph: number[][], numberOfVertexes: number) {
let debug: boolean = true;
let adjVex: number[] = [], // 邻接顶点数组:搜索边的最小权值过程中各边的起点坐标
lowCost = []; // 各边权值数组:搜索边的最小权值过程中各边的权值,数组下标为边的终点。
for (let i = 0; i < numberOfVertexes; i++) // 从图G的下标为0的顶点开始搜索。(也是图G的最小生成树的顶点集合)。
{
adjVex[i] = 0;
}
for (let i = 0; i < numberOfVertexes; i++) // 初始从下标为0的顶点开始到下标为i的顶点的边的权值去搜索。找lowCost中权值最小的下标i。
{
lowCost[i] = graph[0][i];
}
let k: number = 0; // 初始假定权值最小的边的终点的下标为k。
for (let i = 1; i < numberOfVertexes; i++) {
if (debug) {
console.log(`Loop ${i}`);
console.log(`lowCost: ${printArray(lowCost)}`);
console.log(` adjVex: ${printArray(adjVex)}`);
}
// 搜索过程中发现到的最小的权值。初始设置为最大的整数值以示两点间无边。
let minimumWeight: number = Number.MAX_VALUE;
for (let j = 1; j < numberOfVertexes; j++) {
// lowCost中0表示该点已经搜索过了。lowCost[j] < minimumWeight即发现目前最小权值。
if (lowCost[j] != 0 && lowCost[j] < minimumWeight)
{
minimumWeight = lowCost[j]; // 发现目前最小权值。
k = j; // 目前最小权值的边的终点下标。
}
}
if (!debug) {
console.log(`(${adjVex[k]}, ${k})`);// 输出边
}
adjVex[i] = k; // 此时找到的k值即是权值最小的边的终点。将V[k]放入集合U。(这步可省略,因lowCost[j]已被标为“无需搜索”了)。
lowCost[k] = 0; // 0表示该点已经搜索过了,已不需要再被搜索了。
// 转到以V[k]为开始顶点的边,去与前面u为起始顶点到V[i]为终止顶点的边的权值去比较。
for (let j = 1; j < numberOfVertexes; j++)
{
// lowCost中0表示该点已经搜索过了。graph[k][j] < lowCost[j]即发现更小权值。
if (lowCost[j] != 0 && graph[k][j] < lowCost[j])
{
lowCost[j] = graph[k][j]; // 更新权值;索引j即终点下标。
adjVex[j] = k; // 下次寻找权值小的边时,从k为下标的顶点为起点。
}
}
if (debug) {
console.log(`lowCost: ${printArray(lowCost)}`);
console.log(` adjVex: ${printArray(adjVex)}`);
console.log('');
}
}
}
function primSimplified(graph: number[][], numberOfVertexes: number) {
let adjVex: number[] = [], // 邻接顶点数组:搜索边的最小权值过程中各边的起点坐标
lowCost = []; // 各边权值数组:搜索边的最小权值过程中各边的权值,数组下标为边的终点。
for (let i = 0; i < numberOfVertexes; i++) {
adjVex[i] = 0; // 从图G的下标为0的顶点开始搜索。(也是图G的最小生成树的顶点集合)。
lowCost[i] = graph[0][i]; // 初始从下标为0的顶点开始到下标为i的顶点的边的权值去搜索。找lowCost中权值最小的下标i。
}
let k: number = 0; // 初始假定权值最小的边的终点的下标为k。
for (let i = 1; i < numberOfVertexes; i++) {
// 搜索过程中发现到的最小的权值。初始设置为最大的整数值以示两点间无边。
let minimumWeight: number = Number.MAX_VALUE;
for (let j = 1; j < numberOfVertexes; j++) {
// lowCost中0表示该点已经搜索过了。lowCost[j] < minimumWeight即发现目前最小权值。
if (lowCost[j] != 0 && lowCost[j] < minimumWeight)
{
minimumWeight = lowCost[j]; // 发现目前最小权值。
k = j; // 目前最小权值的边的终点下标。
}
}
console.log(`(${adjVex[k]}, ${k})`); // 输出边
lowCost[k] = 0; // 0表示该点已经搜索过了,已不需要再被搜索了。
// 转到以V[k]为开始顶点的边,去与前面u为起始顶点到V[i]为终止顶点的边的权值去比较。
for (let j = 1; j < numberOfVertexes; j++)
{
// lowCost中0表示该点已经搜索过了。graph[k][j] < lowCost[j]即发现更小权值。
if (lowCost[j] != 0 && graph[k][j] < lowCost[j])
{
lowCost[j] = graph[k][j]; // 更新权值;索引j即终点下标。
adjVex[j] = k; // 下次寻找权值小的边时,从k为下标的顶点为起点。
}
}
}
}
function printArray(array: number[]): string {
let str: string[] = [];
str.push("[ ");
for (let i = 0; i < array.length - 1; i++) // 输出数组的前面n-1个
{
str.push(`${toInfinity(array[i])}, `)
}
if (array.length > 0) // 输出数组的最后1个
{
let n: number = array.length - 1;
str.push(`${toInfinity(array[n])}`);
}
str.push(" ]");
return str.join("");
}
function toInfinity(i: number) {
return i == Number.MAX_VALUE ? "∞" : i.toString();
}
function Main() {
let numberOfVertexes: number = 9,
infinity = Number.MAX_VALUE;
let graph: number[][] = [
[0, 10, infinity, infinity, infinity, 11, infinity, infinity, infinity],
[10, 0, 18, infinity, infinity, infinity, 16, infinity, 12],
[infinity, 18, 0, 22, infinity, infinity, infinity, infinity, 8],
[infinity, infinity, 22, 0, 20, infinity, 24, 16, 21],
[infinity, infinity, infinity, 20, 0, 26, infinity, 7, infinity],
[11, infinity, infinity, infinity, 26, 0, 17, infinity, infinity],
[infinity, 16, infinity, 24, infinity, 17, 0, 19, infinity],
[infinity, infinity, infinity, 16, 7, infinity, 19, 0, infinity],
[infinity, 12, 8, 21, infinity, infinity, infinity, infinity, 0],
];
prim(graph, numberOfVertexes);
primSimplified(graph, numberOfVertexes);
}
Main();
参考资料:
《大话数据结构》 - 程杰 著 - 清华大学出版社 第247页
普里姆算法(Prim)邻接矩阵法的更多相关文章
- 最小生成树练习3(普里姆算法Prim)
风萧萧兮易水寒,壮士要去敲代码.本女子开学后再敲了.. poj1258 Agri-Net(最小生成树)水题. #include<cstdio> #include<cstring> ...
- 普里姆算法(Prim)
概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图(带权图)里搜索最小生成树.即此算法搜索到的边(Edge)子集所构成的树中,不但包括了连通图里的所有顶点(Vertex)且其所有边的权 ...
- 普里姆(Prim)算法
概览 普里姆算法(Prim算法),图论中的一种算法,可在加权连通图(即"带权图")里搜索最小生成树.即此算法搜索到的边(Edge)子集所构成的树中,不但包括了连通图里的所有顶点(V ...
- 查找最小生成树:普里姆算法算法(Prim)算法
一.算法介绍 普里姆算法(Prim's algorithm),图论中的一种算法,可在加权连通图里搜索最小生成树.意即由此算法搜索到的边子集所构成的树中,不但包括了连通图里的所有顶点,且其所有边的权值之 ...
- HDU 1879 继续畅通工程 (Prim(普里姆算法)+Kruskal(克鲁斯卡尔))
继续畅通工程 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Sub ...
- hdu 1233:还是畅通工程(数据结构,图,最小生成树,普里姆(Prim)算法)
还是畅通工程 Time Limit : 4000/2000ms (Java/Other) Memory Limit : 65536/32768K (Java/Other) Total Submis ...
- 最小生成树---普里姆算法(Prim算法)和克鲁斯卡尔算法(Kruskal算法)
普里姆算法(Prim算法) #include<bits/stdc++.h> using namespace std; #define MAXVEX 100 #define INF 6553 ...
- ACM第四站————最小生成树(普里姆算法)
对于一个带权的无向连通图,其每个生成树所有边上的权值之和可能不同,我们把所有边上权值之和最小的生成树称为图的最小生成树. 普里姆算法是以其中某一顶点为起点,逐步寻找各个顶点上最小权值的边来构建最小生成 ...
- 图->连通性->最小生成树(普里姆算法)
文字描述 用连通网来表示n个城市及n个城市间可能设置的通信线路,其中网的顶点表示城市,边表示两城市之间的线路,赋于边的权值表示相应的代价.对于n个定点的连通网可以建立许多不同的生成树,每一棵生成树都可 ...
随机推荐
- x64dbg 条件断点相关文档
输入 字符格式 条件断点 Input When using x64dbg you can often use various things as input. Commands Commands ha ...
- 攻防世界 reverse 进阶 9-re1-100
9.re1-100 1 if ( numRead ) 2 { 3 if ( childCheckDebugResult() ) 4 { 5 responseFalse(); 6 } 7 else if ...
- Java学习之路 -- Java怎么学?
@ 目录 java基础怎么学? 学完基础学什么? 几个常用框架学完学什么? MQ JVM的知识跑不掉 微服务等等 其他 数据结构和算法 java基础怎么学? 当时,作为懵懂的小白,大一学习了c和c++ ...
- Python fire库使用
1.前要fire是python中用于生成命令行界面(Command Line Interfaces, CLIs)的工具 不需要做任何额外的工作,只需要从主模块中调用fire.Fire() 它会自动将你 ...
- 第21 章 : Kubernetes 存储架构及插件使用
Kubernetes 存储架构及插件使用 本文将主要分享以下三方面的内容: Kubernetes 存储体系架构: Flexvolume 介绍及使用: CSI 介绍及使用. Kubernetes 存储体 ...
- Java中注释的形式
单行注释 单行注释 // #双斜杠 快捷键:Ctrl + / 多行注释 多行注释 /* */ #单斜杠星号 星号单斜杠 快捷键:Ctrl + shift + / 文档注释 多行注释 /** */ #单 ...
- gdb常用命令(转)
pwn常常会用到gdb,看到一篇不错的文章,记录了很多命令:https://www.jianshu.com/p/c3e5f5972b21 gdb 基础调试命令 s step,si步入 n 执行下一条指 ...
- 在Visual Studio 中使用git——给Visual Studio安装 git插件(二)
在Visual Studio 中使用git--什么是Git(一) 第二部分: 给Visual Studio安装 git插件 如果要使用 git 进行版本管理,其实使用 git 命令行工具就完全足够了, ...
- User-Agent大全 python
1 # -*-coding:utf-8 -*- 2 3 import random 4 5 # 返回一个随机的请求头 headers 6 def getheaders(): 7 # 各种PC端 8 u ...
- 记一次 .NET 某教育系统API 异常崩溃分析
一:背景 1. 讲故事 这篇文章起源于 搬砖队大佬 的精彩文章 WinDBg定位asp.net mvc项目异常崩溃源码位置 ,写的非常好,不过美中不足的是通览全文之后,总觉得有那么一点不过瘾,就是没有 ...