用js来实现那些数据结构15(图01)

其实在上一篇介绍树结构的时候,已经有了一些算法的相关内容介入。而在图这种数据结构下,会有更多有关图的算法,比如广度优先搜索,深度优先搜索最短路径算法等等。这是我们要介绍的最后一个数据结构。同时也是本系列最为复杂的一个。那么我们先来简单介绍一下,什么是图?

一、图的概念

  简单说,图就是网络结构的抽象模型,图是一组由连接的节点(或顶点)。任何二元关系都可以用图来表示。比如我们的地图,地铁线路图等。都是图的实际应用。

  接着我们看看图的一些相关概念和术语。

  一个图G = (V,E)由以下元素组成:

    V:一组顶点。

    E:一组边,链接V中的顶点。

  在继续之前我们先来上张图,继续我们的看图说话。

  请看上图,我们来解释一些概念。

    1、由一条边连接在一起的顶点称为相邻顶点。比如上图中的A和B,A和C,A和D都是相邻的,但是A和E不是相邻的。

    2、一个顶点的取决于其相邻顶点的数量。也就是说,有多少个顶点与其相连,那么它的度就是多少。比如A的度是3,D的度就是4。

    3、路径是顶点V1,V2.....Vn的一个连续序列,其中Vi和Vi+1是相邻的。比如上图中的ACDG,ABEI都是一个路径。

    4、简单路径要求不包含重复的定点。比如ADG就是一条简单路径。

    5、除去最后一个顶点(因为它和第一个顶点时相同的),也是一个简单路径,比如ADCA。

    6、如果图中不存在环。则该图是无环的。

    7、如果图中每两个顶点间都存在路径,则该图是连通的。

  为了便于对比,我又花了一张图。

  跟第一幅图几乎是一样的,只不过我们在路径上加了点东西。

    8、图可以是有向的(边有方向)或者是无向的(边没有方向)。比如上图我们在边上加了方向就变成了有向图。

    9、如果在图中的两个顶点间在双向上都存在路径,则该图是强连通的。比如上图中我们可以说C和D是强连通的。A和B不是强连通的。但是上图并不是一个强连通图。因为上图并不是两个点都有双向的路径。

    10、图还可以是未加权的或是加权的。上图边上加的数字就是加权值。(加权的意思可以简单理解为CSS选择器中的那种权重。)

二、图的表示方法

  我们可以表示图的方法有很多。根据我们要解决问题的类型和图的类型。我们可以选择不同的方法来表示图。下面我们会简单介绍两种表示图的方法。

  1、邻接矩阵。每一个节点都和一个整数相关联,该整数将作为数组的索引。我们用一个二维数组来表示各个顶点之间的连接情况。比如索引为i的节点和索引为j的节点相邻,则表示为arrya[i][j]=1。否则arrya[i][j]=0。

  

  邻接矩阵看起来就是这样子的。要注意我们上面的邻接矩阵只是表示两个顶点是否相邻。我们还需要一个数组来存储所有的顶点。

  但是邻接矩阵会有一些性能问题。比如我们会用很多的空间来表示一些根本就不存在的边。比如上图所有的0。再比如我们想要找到A顶点的相邻顶点,即使A顶点只有一个相邻顶点。我们也必须遍历整个数组才能找到。

  2、邻接表,鉴于以上的问题。我们在本篇中所使用的图的表示方法就是邻接表。邻接表由图中每个顶点的相邻顶点列表所组成。我们可以用数组,链表,map或者hashMap来实现邻接表。

  邻接表看起来就像是上图这样。

  那么我们知道了图的一些基本概念和我们要使用的图的表示方法。下面我们先来完成我们Graph类的架子。

function Map () {
    //......其他各种方法,详见前面的字典部分
}

//代码很简单,但是还是要解释一下。
function Graph() {
    //vertices数组存放我们图中所有的顶点
    var vertices = [];
    //adjList存放我们的邻接表。adjList会使用顶点来作为键,邻接顶点列表作为值
    var adjList = new Map();
    //添加顶点的方法。
    this.addVertices = function (v) {
        //存放到顶点数组中
        vertices.push(v);
        //生成一个还没有邻接顶点列表的Map,因为这时我们已经有顶点了,所以要生成以待使用
        adjList.set(v,[]);
    }
    //这里有个小细节我们需要注意,哦对,这是为图添加边的方法。要注意的是,实际上,在代码中,我们是没有一个东西(变量或者其他什么)来代表边的。
    //我们为两个顶点之间添加一个边实际上只是为两个顶点的邻接表中加入彼此。这样就代表了这两个顶点是相邻的。
    this.addEdge = function (v,w) {
        //而这里我们所实现的图是无向图,所以需要给两个顶点所对应的邻接表加入彼此。
        //而如果是有向图的话,只需要根据方向添加一个就可以了。
        adjList.get(v).push(w);
        adjList.get(w).push(v);
    }

    // 为了方便观察,我们再实现一个toString方法
    // 没啥好说的,双重循环遍历两个数组。
    this.toString = function () {
        var s = "";

        for(var i = 0;i < www.baohuayule.net www.taohuayuan178.com vertices.length;i++) {
            s += vertices[i] + "->";
            var neighbors = adjList.get(vertices[i]);
            for(var j = 0; www.120xh.cn  j www.baohuayule.com < neighbors.length; j++) {
                s += neighbors[jwww.feifanyule.cn] + ‘  ‘;
            }
            s += ‘\n‘;
        }
        return s;
    }
}

//我们来试一下
var graph = new Graph(www.255055.cn/);

var verticesArray = [‘A‘,‘B‘,‘C‘,‘D‘,‘E‘,‘F‘,‘G‘,‘H‘,‘I‘];

for(var i = 0; i < verticesArray.length; i++) {
    graph.addVertices(verticesArray[i]);
}

graph.addEdge(‘A‘,‘B‘);
graph.addEdge(‘A‘,‘C‘);
graph.addEdge(‘A‘,‘D‘);
graph.addEdge(‘C‘,‘D‘);
graph.addEdge(‘C‘,‘G‘);
graph.addEdge(‘D‘,‘G‘);
graph.addEdge(‘D‘,‘H‘);
graph.addEdge(‘B‘,‘E‘);
graph.addEdge(‘B‘,‘F‘);
graph.addEdge(‘E‘,‘I‘);

console.log(graph.toString());
/*
A->B  C  D
B->A  E  F
C->A  D  G
D->A  C  G  H
E->B  I
F->B
G->C  D
H->D
I->E
*/

  那么我们就实现了Graph类中最简单的部分——如何添加顶点和边。大家会不会觉得有点简单了。嘿嘿.....有趣的还在后面,别急......

  好了,那么到这里这篇文章就结束了。下一篇文章我们再继续学习图的遍历。

用js来实现那些数据结构15(图01)

原文地址:https://www.cnblogs.com/qwangxiao/p/8996345.html

时间: 2024-11-02 03:06:25

用js来实现那些数据结构15(图01)的相关文章

原生JS面向对象思想封装轮播图组件

原生JS面向对象思想封装轮播图组件 在前端页面开发过程中,页面中的轮播图特效很常见,因此我就想封装一个自己的原生JS的轮播图组件.有了这个需求就开始着手准备了,代码当然是以简洁为目标,轮播图的各个功能实现都分别分为不同的模块.目前我封装的这个版本还不适配移动端,只适配PC端. 主要的功能有:自动轮播,点击某一张图片对应的小圆点就跳转到指定图片,有前后切换按钮.使用的时候只需要传入图片的路径以及每张图片分别所对应的跳转路径还有目标盒子ID就可以了,还可以自定义每张图轮播的延时,不过延时参数不是必须

数据结构之图 Part3 – 2 遍历

BFS using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace LH.GraphConsole { class Program { private static bool[] visited; private static Queue<int> rootVertexQueue = new Queue<int>(); static void Main

数据结构之图 Part3 – 1 遍历

DFS using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace LH.GraphConsole { class Program { private static bool[] visited; static void Main(string[] args) { DFSTranverse(); } private static void DFSTranverse(

JS案例之4——Ajax多图上传

近期项目中有好几次用到多图上传,第一次在项目中真正用到Ajax技术,稍微整理了下,贴个案例出来. 我们传统的做法是当用户提交一个表单时,就向web服务器端发送一个请求.服务器接受并处理传来的表单信息,处理完成后返回一个新的页面.这个做法比较浪费带宽,当请求数较多时,页面响应的时间就依赖于服务器处理的时间. 而Ajax应用仅向服务器发送并取回必需的数据,其他不需要的数据不用响应,它使用SOAP或其它一些基于XML的web service接口,并在客户端采用JS来处理来自服务器的响应.因此在服务器和

数据结构:图的实现--邻接矩阵

图结构的邻接矩阵实现 为了表现图中顶点之间的关联,我们可以使用邻接矩阵来实现图结构.所谓的邻接矩阵,就是一个反应边与边之间联系的二维数组.这个二维数组我们用matrix[numV][numV]表示,其中numV是顶点数. 对于无权图 若顶点Vi和Vj之间有边,则matrix[Vi][Vj]=1;否则matrix[Vi][Vj]=0. 对于有权图 若顶点Vi和Vj之间有边,且权值为weight,则matrix[Vi][Vj]=weight;否则matrix[Vi][Vj]=0或MAXWEIGHT(

数据结构之图 Part2 - 1

邻接矩阵 网上很少有C# 写图的数据结构的例子,实际的项目中也从来没用过Array 这坨东西,随手写个,勿喷. namespace LH.GraphConsole { public struct Graph { public Graph(int vertexNumber, int edgeNumber) { VertexNumber = vertexNumber; EdgeNumber = edgeNumber; Vertexs = new string[VertexNumber]; Edges

数据结构之图 Part1

Part 1 预计使用7天的时间来过掉图相关的数据结构.第一天主要是一天图的基本概念,熟练掌握定义是一切交流和沟通的基础. 1定义 1.1图 有穷非空顶点,外加边. G(V,E) Graph Vertex Edge 顶点就是 点,有穷非空. 顶点之间的关系就是边,边可空. 1.2 分类 无向边:无方向的边. 有向边:有方向的边,弧. 简单图:无重复边和自己到自己的顶点. 带权的图称为网. 无向图的度:顶点的边数. 有向图的度:顶点的弧的数量分为入度和出度. 连通图:任意两点有路径. 生成树:无向

数据结构:图--拓扑排序

拓扑排序 拓扑排序 在实际应用中,有向图的边可以看做是顶点之间制约关系的描述.把顶点看作是一个个任务,则对于有向边<Vi,Vj>表明任务Vj的完成需等到任务Vi完成之后,也就是说任务Vi先于任务Vj完成.对于一个有向图,找出一个顶点序列,且序列满足:若顶点Vi和Vj之间有一条边<Vi,Vj>,则在此序列中顶点Vi必在顶点Vj之前.这样的一个序列就称为有向图的拓扑序列(topological order). 步骤 从有向图中选取一个没有前驱(入度为0)的顶点输出. 删除图中所有以它为

数据结构:图的实现--邻接表

使用邻接表实现图结构 当图中的边数较少时,用邻接表来实现图结构,则会浪费很多内存空间.因此,考虑另一种实现图结构的方法:邻接表.在邻接表中主要有两种节点结构体: 顶点节点 边节点 直接看代码 类定义 #include<iostream> #include<iomanip> using namespace std; //最大权值 #define MAXWEIGHT 100 //边节点 typedef struct edgenode_tag { int adjvex; //邻接点 in