代码改变世界

数据结构-图(非带权图)(js)

2010-08-15 13:57  Clingingboy  阅读(1465)  评论(0编辑  收藏  举报

 

好久没js

1.顶点

//定义顶点
var Vertex = function (label) {
    this._label = label;
    this._wasVisited = false;
}

2.图

//定义图
var Graph = function () {
    var max_vertx = 20;
    this.vertexList = new Array(max_vertx);
    this.adjMat = [];
    this.length = 0;
    for (var i = 0; i < max_vertx; i++) {
        this.adjMat.push([]);
        for (var j = 0; j < max_vertx; j++) {
            this.adjMat[i][j] = 0;
        }
    }
};

3.添加顶点和边

//添加顶点
Graph.prototype.AddVertex = function (label) {
    var vertex = new Vertex(label);
    this.vertexList.push(vertex);
    this.length++;
};
//添加边
Graph.prototype.AddEdge = function (start, end) {
    adjMat[start][end] = 1;
    adjMat[end][start] = 1;
}


4.深度优先遍历

规则:
1.访问一个领接点未访问的顶点并标记为访问,然后放入栈中
2.如果1无法执行且栈不为空,则弹出一个顶点然后继续执行1
3.无法1,2均无法执行则结束遍历

so先定义一个栈

Stack

var Stack = function () {
    this._array = new Array(10);
    this.top = -1;
}
Stack.prototype.Push = function (obj) {
    this._array[++this.top] = obj;
};
Stack.prototype.Peek = function () {
    return this._array[this.top];
};
Stack.prototype.Pop = function () {
    return this._array[this.top--];
};
Stack.prototype.IsEmpty = function () {
    return this.top == -1;
};

(1)把第一个放入栈
if (this.length == 0) return;
this.vertexList[0].wasVisited = true;
this.vertexList[0].Display();
this.vertStack.Push(0);
(2)取邻接点
var length = this.length;
var adjMat = this.adjMat;
var vertexList = this.vertexList;
var unvisitedVertex = function (v) {
    for (var i = 0; i < length; i++) {
        if (adjMat[v][i] == 1 && !vertexList[i].wasVisited)
            return i;
    }
    return -1;
}
(3)在栈不为空的情况下,并进行标记遍历
while (!this.vertStack.IsEmpty()) {
    var v = unvisitedVertex(this.vertStack.Peek());
    if (v == -1)
        this.vertStack.Pop();
    else {
        this.vertexList[v].wasVisited = true;
        this.vertexList[v].Display();
        this.vertStack.Push(v);
    }
}
Test
var entity = new Graph();
//添加顶点
entity.AddVertex("A");
entity.AddVertex("B");
entity.AddVertex("C");
entity.AddVertex("D");
entity.AddVertex("E");
//添加边
entity.AddEdge(0, 1);//AB
entity.AddEdge(1, 2); //BC
entity.AddEdge(0, 3); //AD
entity.AddEdge(3, 4); //DE
 entity.dfs();


5.广度优先遍历
规则:

1.访问当前点的所有邻接点,标记它,并放入队列中
2.如果邻接点访问完毕后,则从队列中取一个邻接点重复1步骤
3.当1和2完毕后则完成
先定义一个Queue

var Queue = function () {
    this.Max_Size = 10;
    this._array = new Array(this.Max_Size);
    this.head = 0;
    this.rear = -1;
}
Queue.prototype.Enqueue = function (obj) {
    this._array[++this.rear] = obj;
};
Queue.prototype.Dequeue = function () {
    return this._array[this.head++];
};
Queue.prototype.IsEmpty = function () {
    return (this.rear + 1 == this.head || (this.head + this.Max_Size - 1 == this.rear));
};

bfs
1.标记第一个点

this.vertexList[0].wasVisited = true;
this.vertexList[0].Display();
this.vertQueue.Enqueue(0);

2.当有邻接点则显示,否则则从队列中取

while (!this.vertQueue.IsEmpty()) {
    var v1 = this.vertQueue.Dequeue();
    var v2;
    while ((v2=unvisitedVertex(v1))!=-1) {
        this.vertexList[v2].wasVisited = true;
        this.vertexList[v2].Display();
        this.vertQueue.Enqueue(v2);
    }
}
完整
Graph.prototype.bfs = function () {
    if (this.length == 0) return;
    this.vertexList[0].wasVisited = true;
    this.vertexList[0].Display();
    this.vertQueue.Enqueue(0);

    var length = this.length;
    var adjMat = this.adjMat;
    var vertexList = this.vertexList;
    var unvisitedVertex = function (v) {
        for (var i = 0; i < length; i++) {
            if (adjMat[v][i] == 1 && !vertexList[i].wasVisited)
                return i;
        }
        return -1;
    }
    while (!this.vertQueue.IsEmpty()) {
        var v1 = this.vertQueue.Dequeue();
        var v2;
        while ((v2=unvisitedVertex(v1))!=-1) {
            this.vertexList[v2].wasVisited = true;
            this.vertexList[v2].Display();
            this.vertQueue.Enqueue(v2);
        }
    }
}


6.最小生成树
一个图的最小生成树可能有很多种,
采用深度遍历.不同之处在于将当前值给记录下来,
与4比较

Graph.prototype.mst = function () {
    if (this.length == 0) return;
    this.vertexList[0].wasVisited = true;
    this.vertStack.Push(0);

    var length = this.length;
    var adjMat = this.adjMat;
    var vertexList = this.vertexList;
    var unvisitedVertex = function (v) {
        for (var i = 0; i < length; i++) {
            if (adjMat[v][i] == 1 && !vertexList[i].wasVisited)
                return i;
        }
        return -1;
    }
    while (!this.vertStack.IsEmpty()) {
        var currentVertex = this.vertStack.Peek();
        var v = unvisitedVertex(currentVertex);
        if (v == -1)
            this.vertStack.Pop();
        else {
            this.vertexList[v].wasVisited = true;
            this.vertexList[currentVertex].Display();
            this.vertexList[v].Display();
            this.vertStack.Push(v);
        }
    }
}

7.拓扑排序

在有向图的情况下,如课程选择,有先后顺序原则.
规则:
1.找到一个没有后继的顶点,删除这个顶点并做标记,并重复,直到删除完为止
(1)有向图只需要添加一边

Graph.prototype.AddSingleEdge = function (start, end) {
    this.adjMat[start][end] = 1;
};

(2)delete

      Graph.prototype.DeleteVertex = function (index) {
          var nVerts = this.length;
          if (index != this.length - 1) {
              //move
              for (var i = index; i < nVerts - 1; i++) {
                  this.vertexList[i] = this.vertexList[i + 1];
              }
              //delete arrry from table
              //move up
              for (var i = index; i < nVerts - 1; i++) {
                  this.moveRowUp(i, nVerts);
              }
              //move left
              for (var i = index; i < nVerts - 1; i++) {
                  this.moveColLeft(i, nVerts-1);
              }
          }
          this.length--;
      };
Graph.prototype.moveRowUp=function(row, length)
{
for(var col=0; col<length; col++)
   this.adjMat[row][col] = this.adjMat[row+1][col];
}
Graph.prototype.moveColLeft = function (col, length) {
    for (var row = 0; row < length; row++)
        this.adjMat[row][col] = this.adjMat[row][col + 1];
}

(3)topo

Graph.prototype.Topo = function () {
    
    while (this.length > 0) {
        var currentVertex = this.noSuccessors();
        if (currentVertex == -1)
            return;
        this.sortArray[this.length-1]=this.vertexList[currentVertex]._label;
        this.DeleteVertex(currentVertex);
    }
};
Graph.prototype.noSuccessors = function () {
    var isEdge = false;
    for (var i = 0; i < this.length; i++) {
        isEdge = false;
        for (var j = 0; j < this.length; j++) {
            if (this.adjMat[i][j] > 0) {
                isEdge = true;
                break;
            }
        }
        if (!isEdge)
            return i;
    }
    return -1;
};


8.Warshall算法