1.大理论的一些资料
带权图
带权是说的是在图的连接边是有长度。我们来模拟这个环境:
中国的20个城市,每个城市好比一个图的顶点,火车在地面上开,有火车的轨道将20个城市连接在一起了
而火车的轨道好比是边,而轨道连接各个城市之间的的有长度的,那么这就形成了一个图—-有火车的轨道网络,
这个例子说的就是带权的图了。
当把权值当做边的特性的时候,一些有趣的并且复杂的问题就出现了,
什么是带权的最小生成树?
什么是两个顶点间的最短距离?
这两个问题都在现实的生活中有非常大的意义的
2.小理论的一些资料(重要概念)
带权图的最小生成树
我们先来看普通的最小生成树。在有向图中创建一个树比在无向图中要复杂哦。当所有的边拥有相同的权值,问题就变的简单了,
算法可以任意选择一条边加入最小生成树。但是当边具有不同的权值时,需要用一些算法策略来选择正确的边。
一个实例:丛林中的有线电视
假设要再一个虚拟的国家M的6个城市之间架设有线电视网络,把它们都连接起来。五条边可以连接6个点,但是要怎么连接五条边呢
才能让线路最短。
步骤1.
随便 找一个顶点A,作为办公地点
步骤2.
找出各个直接与A连接的点,并且比较出最小的那条边。连接这条边的点就作为第二办公地点B,并且将这边架设好
步骤3.
规则1 已经架设好的边不修改
规则2 新建的办公地点开始办公,步骤类似于步骤2,并且将步骤2中遗留下来的边的长度一起比较,选择出最短的那条作为下一个办公点
步骤4
直到没有边或者全部连接好了顶点了,那么就停止了 ,连接线就是最短的线了。(其实表示还是不详细哦)
三类顶点
1.已经有办事处并且用电缆连接的城市,他们是最小生成树的顶点
2.还没有连接,也没有办事处的城市,但是知道了他们连接到至少有一个已经有办事处的城市电缆的安装造价了。
这些城市就叫做边缘城市
3还不知道任何信息的城市的
随着算法的进行,城市虫第三类到第二类到第一类
设计算法:
优先级队列
正如前面例子描述的那样,执行算法的关键行为是保存两个城市建立连接的造价单。通过选择造价最低的项,就可以决定下一条建在何处
建议用优先级队列来实现这个用于反复选择最小造价价值的表,而不用链表或者数组。这是解决最小生成树的有效方式。在正式的程序中,
优先级队列可能基于堆来实现。这加快了加大的优先级队列的操作,然而,在实例中,将用数组实现的队列进行优先级队列。
算法要点
下面用图的术语,重申下算法:
从一个顶点开始,把它放入树的集合中,然后重复做下面的事情:
1.找到最新的顶点到其他顶点的所以边,这些顶点不能在树的集合中,把这些边放入优先级队列中
2.找出权值最小的边,把它和塔所到达的顶点放入树 的结合中。
重复这些步骤,直到所以项目的顶点都在树的集合中了。这是工作就结束了。
在步骤1,最新的意味着最近放入树中的。此步骤的边可以在邻接矩阵中找到,步骤1完成后,表中包含了所有的边,这些边都是从树中顶点
到它们的不在树中的邻接点的连接
无用边
在表剩余条目中,想要把某些连接删除比较困难,它们都是从当前城市到已经拥有办事处的城市的连接,但是如果不做这个工作,就可能会导致
安装不必要的优先电缆
在程序的算法中,也要确保优先级队列中不能有连接已在书中的顶点的边,每次向树中增加顶点后,都要遍历优先级队列查找并删除这样的边,
这样做以后,要使优先队列中任意时刻只保存一条树中顶点到某边缘点的边就变得容易了,也就是说,优先级队列中应该包含一条到达
某个第二类顶点的边
部分代码
package endual;
public class ValueGraph {
/**
* 有权图的最小生成树的方法mstw()
*/
public void mstw() {
currentVert = 0 ; //选择从开始点出发
/**
* 算法中while中执行,循环结束条件是所以顶点都在书中了,循环中完成下面的操作
* 1.当前的顶点放入到树中去,从第一个开始
* 2.连接这个顶点的边全部放入到优先级队列中(如果合适)
* 3.从优先级队列中删除权值最小的边。这条边的目的顶点变成当前顶点
*
* 在看看这些步骤的细节、
* 在步骤1中,通过标记currentVert所指顶点的isInTree字段来表示该顶点放入树中
* 在步骤2中,连接这个顶点的边插入优先级队列。通过在连接矩阵中扫描号是currentVert的
* 行寻找需要的边。只要下面任意的一个条件为真,那么这条边就不能放入到队列中
*
* 1.源点和终点是相同的
* 2.原点在树中了(重点看下这个概念)
* 3.源点和终点之间没有边(链接矩阵中对于的值等于无限大)
*
* 如果没有一个条件为真,调用putInPQ()方法把这条边放入到这个优先队列中。实际上,正如下面要到的,这个列程并不总是把
* 边放入到优先队列中去的
*
* 在步骤三种,将最小权值的边从优先级队列中删掉,把这条边和该边的终点加入树,并显示原点和终点
*
* 最后的for循环将数据复原
*
*
*
*/
while (nTree
全部代码
首先我们创建边了
package endual;
public class Edge {
public int srcVert ; //一个顶点开始的序列好
public int destVert ; //一个顶点结束的序号
public int distance ;//从开始到介绍的长度
public Edge(int srcVert, int destVert, int distance) {
super();
this.srcVert = srcVert;
this.destVert = destVert;
this.distance = distance;
}
}
然后我们创建顶点了
package endual;
public class Vertex {
private char label; // 顶点的标记
private boolean isInTree; // 是否在最小生成树中了
private boolean isVisited; // 是否已经被访问
public Vertex(char label) {
super();
this.label = label;
this.isInTree = false;
this.isVisited = false;
}
public char getLabel() {
return label;
}
public void setLabel(char label) {
this.label = label;
}
public boolean isInTree() {
return isInTree;
}
public void setInTree(boolean isInTree) {
this.isInTree = isInTree;
}
public boolean isVisited() {
return isVisited;
}
public void setVisited(boolean isVisited) {
this.isVisited = isVisited;
}
}
我们创建优先队列 是基于数组的哦
package endual;
public class PriorityQ {
private final int SIZE = 20;
private Edge[] queArray;
private int size;
public PriorityQ() {
super();
this.queArray = new Edge[this.SIZE];
this.size = 0; // 当前队列中的数目
}
// 插入边长
public void insert(Edge item) {
int j;
for (j = 0; j this.queArray[j].distance) {
break;
} // 如果当前插入的边长当前的节点长度大,那么就停止掉,寻找到数组中的位子
// 因为现在数组的位子是有人的,那么就以为,把这个位子空出来
for (int k = this.size - 1; k >= j; k--) {
this.queArray[k + 1] = this.queArray[k];
}
// 空出来的位子就插入进去
this.queArray[j] = item;
size++; // 当前队列中的数要增加一个
}
} // end
// 移除最小的那个边
public Edge removeMin() {
this.size = this.size - 1;
return this.queArray[this.size];
}
public void removeN(int n) { //移除在数组中为是n的数据
for (int j=n; j
然后我们创建图了,在图中创建方法
package endual;
public class Graph {
private final int MAX_SIZE = 20;
private Vertex[] vertexList;
private final int INFINITY = 10000000; // 认为是这个无限大的,测试两个点之间的距离是不是之间相连的
private int adjMat[][]; // 存放在顶点是不是连接点,也就是也矩阵的方式进行存放
private int nVerts; // 当前图中的数量
private int currentVert;
private PriorityQ thePQ;
private int nTree; // 当前树的长度
public Graph() {
super();
this.vertexList = new Vertex[this.MAX_SIZE];
this.adjMat = new int[19][19];
this.initialAdjMat();
this.nVerts = 0;
this.currentVert = 0;
this.thePQ = new PriorityQ();
this.nTree = 0;
}
private void initialAdjMat() {
for (int i = 0; i dis) {
//如果老边的长度是大于新边的长度的话
thePQ.removeN(queueIndex) ; //移除这个老的节点
Edge theEdge = new Edge(this.currentVert,i, dis) ;//创建一个新的边
thePQ.insert(theEdge) ; //插入到新的队列中
}
else {//如果没有这样的边
Edge theEdge = new Edge(this.currentVert,i, dis) ;//创建一个新的边
thePQ.insert(theEdge) ; //插入到新的队列中
}
}
}
}
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net
相关推荐: 声音克隆,精致细腻,人工智能AI打造国师“一镜到底”鬼畜视频,基于PaddleSpeech(Python3.10)
电影《满江红》上映之后,国师的一段采访视频火了,被无数段子手恶搞做成鬼畜视频,诚然,国师的这段采访文本相当经典,他生动地描述了一个牛逼吹完,大家都信了,结果发现自己没办法完成最后放弃,随后疯狂往回找补的过程。 最离谱的是,他这段采访用极其丰富的细节描述了一个没…