数据结构图(带权图)(js)
一.最小生成樹
永遠遵循取最小權值的原則
如一個頂點到多個頂點,取最小權值
1.添加邊結構
var Edge = function (sv, dv, d) {
//起始點
this.srcVert = sv;
//重點
this.destVert = dv;
//權值
this.distance = d;
}
2.添加優先級隊列
var PriorityQ = function () {
this.queArray = [];
this.Max_Size = 10;
this.length = 0;
};
PriorityQ.prototype.Insert = function (item) {
var i;
//compute distance index
for (i = 0; i < this.length; i++) {
if (item.distance >= this.queArray[i].distance)
break;
}
//move
for (var j = this.length - 1; j >= i; j--) {
this.queArray[j + 1] = this.queArray[j];
}
this.queArray[i] = item;
this.length++;
};
PriorityQ.prototype.remove = function () {
if (arguments.length == 0)
return this.queArray[--this.length];
if (arguments.length == 1) {
for (var j = arguments[0]; j < this.length - 1; j++) {
this.queArray[j] = this.queArray[j + 1];
}
this.length--;
}
};
PriorityQ.prototype.peek = function () {
if (arguments.length == 0)
return this.queArray[this.length - 1];
if (arguments.length == 1) {
return this.queArray[arguments[0]];
}
};
PriorityQ.prototype.IsEmpty = function () {
return this.length == 0;
}
PriorityQ.prototype.find = function (dex) {
for (var j = 0; j < this.length; j++) {
if (this.queArray[j].destVert == dex)
return j;
}
return -1;
}
3.1 標記當前項
this.getCurrentVertex().isInTree = true; nTree++;
3.2將符合條件的權值放入隊列中
for (var j = 0; j < this.length; j++) {
//skip
//if it's us
//in the tree
//no edge
if (j == this.currentVertIndex)
continue;
if (this.vertexList[j].isInTree)
continue;
var distance = this.adjMat[this.currentVertIndex][j];
if (distance == 0)
continue;
//put in pq
//ensure index and distance
this.putInPQ(j, distance);
}
如遇到起點相同的,則比較distance,放棄distance長的那個.
Graph.prototype.putInPQ=function(newVert, newDist)
{
var queueIndex = this.thePQ.find(newVert);
if (queueIndex != -1) {
var tempEdge = this.thePQ.peek(queueIndex);
var oldDist = tempEdge.distance;
//compare distance
if (oldDist > newDist) {
this.thePQ.remove(queueIndex);
var theEdge = new Edge(this.currentVertIndex, newVert, newDist);
this.thePQ.Insert(theEdge);
}
}
else {
//insert directly
var theEdge = new Edge(this.currentVertIndex, newVert, newDist);
this.thePQ.Insert(theEdge);
}
}
3.4.取最小權值
if (this.thePQ.length == 0) return; //remove minium distance from dq var theEdge = this.thePQ.remove(); var srcVert = theEdge.srcVert; this.currentVertIndex = theEdge.destVert; //display this.vertexList[srcVert].Display(); this.vertexList[this.currentVertIndex].Display();
完整示例
Graph.prototype.getCurrentVertex=function()
{
return this.vertexList[this.currentVertIndex];
}
Graph.prototype.mstw = function () {
var nTree = 0;
while (nTree < this.length - 1) {
//put CurrentVertex in tree
this.getCurrentVertex().isInTree = true;
nTree++;
for (var j = 0; j < this.length; j++) {
//skip
//if it's us
//in the tree
//no edge
if (j == this.currentVertIndex)
continue;
if (this.vertexList[j].isInTree)
continue;
var distance = this.adjMat[this.currentVertIndex][j];
if (distance == 0)
continue;
//put in pq
//ensure index and distance
this.putInPQ(j, distance);
}
if (this.thePQ.length == 0) return;
//remove minium distance from dq
var theEdge = this.thePQ.remove();
var srcVert = theEdge.srcVert;
this.currentVertIndex = theEdge.destVert;
//display
this.vertexList[srcVert].Display();
this.vertexList[this.currentVertIndex].Display();
}
}
Graph.prototype.putInPQ=function(newVert, newDist)
{
var queueIndex = this.thePQ.find(newVert);
if (queueIndex != -1) {
var tempEdge = this.thePQ.peek(queueIndex);
var oldDist = tempEdge.distance;
//compare distance
if (oldDist > newDist) {
this.thePQ.remove(queueIndex);
var theEdge = new Edge(this.currentVertIndex, newVert, newDist);
this.thePQ.Insert(theEdge);
}
}
else {
//insert directly
var theEdge = new Edge(this.currentVertIndex, newVert, newDist);
this.thePQ.Insert(theEdge);
}
}
二.求最短路徑
迪杰斯特拉(Dijkstra)算法求頂點0到其他各頂點的最短路徑
1.用于保存之前頂點到當前頂點的距離
class DistPar // distance and parent
{ // items stored in sPath array
public int distance; // distance from start to this vertex
public int parentVert; // current parent of this vertex
// -------------------------------------------------------------
public DistPar(int pv, int d) // constructor
{
distance = d;
parentVert = pv;
}
// -------------------------------------------------------------
} // end class DistPar
2.將第一個頂點標記為在樹中
int startTree = 0; // start at vertex 0
vertexList[startTree].isInTree = true;
nTree = 1; // put it in tree
3.初始化讀取頂點到各個頂點的距離,如果沒有邊則距離為無窮大
// transfer row of distances from adjMat to sPath
for(int j=0; j<nVerts; j++)
{
int tempDist = adjMat[startTree][j];
sPath[j] = new DistPar(startTree, tempDist);
}
4.進入回圈
4.1在各點中取距離最小的點
int indexMin = getMin(); // get minimum from sPath int minDist = sPath[indexMin].distance;
4.2記錄距離最小的點的索引值和距離,并把該頂點標記入樹
if(minDist == INFINITY) // if all infinite
{ // or in tree,
System.out.println("There are unreachable vertices");
break; // sPath is complete
}
else
{ // reset currentVert
currentVert = indexMin; // to closest vert
startToCurrent = sPath[indexMin].distance;
// minimum distance from startTree is
// to currentVert, and is startToCurrent
}
// put current vertex in tree
vertexList[currentVert].isInTree = true;
4.3 當把當前索引頂點記錄之后,然后獲取該頂點到各頂點的距離
int column = 1; // skip starting vertex
while(column < nVerts) // go across columns
{
int currentToFringe = adjMat[currentVert][column];
}
4.4記錄上個距離和當前距離的和
int startToFringe = startToCurrent + currentToFringe;
4.5與第一個頂點到該節點的距離和startToFringe 進行比較,然后取短路徑.并更新sPath的頂點和距離.
比如A到B是60,B到C是50,A到C是150,那么A經過B再到C的路徑小于A直接到C的距離,則產生了最小路徑
int sPathDist = sPath[column].distance;
// compare distance from start with sPath entry
if(startToFringe < sPathDist) // if shorter,
{ // update sPath
sPath[column].parentVert = currentVert;
sPath[column].distance = startToFringe;
}
完整(核心)
public void adjust_sPath()
{
// adjust values in shortest-path array sPath
int column = 1; // skip starting vertex
while(column < nVerts) // go across columns
{
// if this column's vertex already in tree, skip it
if( vertexList[column].isInTree )
{
column++;
continue;
}
// calculate distance for one sPath entry
// get edge from currentVert to column
int currentToFringe = adjMat[currentVert][column];
// add distance from start
int startToFringe = startToCurrent + currentToFringe;
// get distance of current sPath entry
int sPathDist = sPath[column].distance;
// compare distance from start with sPath entry
if(startToFringe < sPathDist) // if shorter,
{ // update sPath
sPath[column].parentVert = currentVert;
sPath[column].distance = startToFringe;
}
column++;
} // end while(column < nVerts)
}
等sPath更新完畢后就是最小路徑了
輸出
Shortest paths
CurrentVert 1 distance 50
before begin sPath----------------
ParentVert/SelfVert 0 0 InTree true distance 1000000
ParentVert/SelfVert 0 1 InTree true distance 50
ParentVert/SelfVert 0 2 InTree false distance 1000000
ParentVert/SelfVert 0 3 InTree false distance 80
ParentVert/SelfVert 0 4 InTree false distance 1000000
before end sPath----------------
Start/Vert/column 0 1 2 distance 60 total undirect 110 sPathDist direct 1000000
2 changed
Start/Vert/column 0 1 3 distance 90 total undirect 140 sPathDist direct 80
Start/Vert/column 0 1 4 distance 1000000 total undirect 1000050 sPathDist direct 1000000
adjusted begin sPath----------------
ParentVert/SelfVert 0 0 InTree true distance 1000000
ParentVert/SelfVert 0 1 InTree true distance 50
ParentVert/SelfVert 1 2 InTree false distance 110
ParentVert/SelfVert 0 3 InTree false distance 80
ParentVert/SelfVert 0 4 InTree false distance 1000000
adjusted end sPath----------------
CurrentVert 3 distance 80
before begin sPath----------------
ParentVert/SelfVert 0 0 InTree true distance 1000000
ParentVert/SelfVert 0 1 InTree true distance 50
ParentVert/SelfVert 1 2 InTree false distance 110
ParentVert/SelfVert 0 3 InTree true distance 80
ParentVert/SelfVert 0 4 InTree false distance 1000000
before end sPath----------------
Start/Vert/column 0 3 2 distance 20 total undirect 100 sPathDist direct 110
2 changed
Start/Vert/column 0 3 4 distance 70 total undirect 150 sPathDist direct 1000000
4 changed
adjusted begin sPath----------------
ParentVert/SelfVert 0 0 InTree true distance 1000000
ParentVert/SelfVert 0 1 InTree true distance 50
ParentVert/SelfVert 3 2 InTree false distance 100
ParentVert/SelfVert 0 3 InTree true distance 80
ParentVert/SelfVert 3 4 InTree false distance 150
adjusted end sPath----------------
CurrentVert 2 distance 100
before begin sPath----------------
ParentVert/SelfVert 0 0 InTree true distance 1000000
ParentVert/SelfVert 0 1 InTree true distance 50
ParentVert/SelfVert 3 2 InTree true distance 100
ParentVert/SelfVert 0 3 InTree true distance 80
ParentVert/SelfVert 3 4 InTree false distance 150
before end sPath----------------
Start/Vert/column 0 2 4 distance 40 total undirect 140 sPathDist direct 150
4 changed
adjusted begin sPath----------------
ParentVert/SelfVert 0 0 InTree true distance 1000000
ParentVert/SelfVert 0 1 InTree true distance 50
ParentVert/SelfVert 3 2 InTree true distance 100
ParentVert/SelfVert 0 3 InTree true distance 80
ParentVert/SelfVert 2 4 InTree false distance 140
adjusted end sPath----------------
CurrentVert 4 distance 140
before begin sPath----------------
ParentVert/SelfVert 0 0 InTree true distance 1000000
ParentVert/SelfVert 0 1 InTree true distance 50
ParentVert/SelfVert 3 2 InTree true distance 100
ParentVert/SelfVert 0 3 InTree true distance 80
ParentVert/SelfVert 2 4 InTree true distance 140
before end sPath----------------
adjusted begin sPath----------------
ParentVert/SelfVert 0 0 InTree true distance 1000000
ParentVert/SelfVert 0 1 InTree true distance 50
ParentVert/SelfVert 3 2 InTree true distance 100
ParentVert/SelfVert 0 3 InTree true distance 80
ParentVert/SelfVert 2 4 InTree true distance 140
adjusted end sPath----------------
A=inf(A) B=50(A) C=100(D) D=80(A) E=140(C)
步驟總結:
1.選定一個頂點為根記做A
2.選擇該頂點的最小邊記做B,并記錄這條邊與A相交的頂點C,并標記入樹C
3.計算C點到各頂點(不在樹中的)的邊的長度并與(A到各頂點的邊)相比較,選擇路徑小者對A進行更新,并記錄該頂點(以便排序頂點輸出)
4.重復2-3步驟,等所有頂點都在樹中時,則A到各頂點的最小路徑更新完畢
這屬于一個貪婪算法,總是先選最小的權值
終于搞懂了 理解后,其實也不難.多看看中間步驟,一步到位很難理解
三.弗洛伊德(Floyed)算法求每一對頂點之間的最短路徑的
總結
以上是生活随笔為你收集整理的数据结构图(带权图)(js)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MYSQL数据库VALUES_MYSQL
- 下一篇: AMD R7 7840HS 核显 780