zoukankan      html  css  js  c++  java
  • JavaScript--数据结构与算法之图

    图和图的算法:
    图的定义:由边的集合及顶点的集合组成。
    例如地图,每个城镇是顶点,道路是边,由顶点对来定义(城镇1,城镇2)简称(v1,v2)顶点也有权重——成本。
    基本概念:
    有向图:图的顶点对是有序的。——有箭头(常用的流程图)
    无向图:图是无序的。——无箭头指向的。
    路径:图中一系列顶点构成。
    路径长度:路径中第一个顶点到最后一个顶点之间的数量表示。
    环:指向自身的顶点组成的路径。环的长度为0;
    圈:至少有一条边的路径,且路径的第一个定点和最后一个顶点相同。
    简单圈:无论是有向图还是无向图,只要是没有重复边或重复顶点的圈。
    平凡圈:除了第一个和最后一个顶点以外,路径的其他顶点有重复的圈。
    强连通:两个顶点之间有路径,这两个顶点之间是强连通的,反之亦然。
    强连通图:有向图的所有顶点都是强连通的。
    一、图类:
    图和树,二叉树很像。一可以试用数的方式创建一个图,节点表示一个顶点。但用基于对象的方式去处理会产生问题,因为图会增长到非常大。这样树的结构的效率会很低下。
    1.1 顶点的表示:
    和二叉树的穿件基本一致,先创建一个顶点类Vertex来保存顶点和边。里面有两个成员。一个用于标识顶点label,另一个表明这个顶点是否被访问过的布尔值wasVisited.
            function Vertex(label) {
                this.label = label;
            }
    1.2 表示边
      图的信息都保存在边上,因为他们描述了图的结构。当然不能像二叉树的表现形式那样,因为他很固定一个父节点只能有两个子节点。而图的结构要灵活得多,一个顶点可以有一条边,多条边和他相连。
    1.2.1 邻接表(邻接表数组):数组与链表相结合的存储方法。
      邻接表的处理方法:
      1、图中顶点用一个一维数组存储,另外,对于顶点数组中,每个数据元素还需要存储指向第一个邻接点的指针,以便于查找该顶点的边信息。
      2、图中每个顶点vi的所有邻接点构成一个线性表,由于邻接点的个数不定,所以用单链表存储,无向图称为顶点vi的边表,有向图称为顶点vi作为弧尾的出边表。
      左边是一维数组,表示顶点,右边用链表表示图中每个顶点所有的邻接点构成的线性表。
      表示图最佳方法。江边存储为由顶点的相邻顶点列表构成的数组,并以此顶点作为索引。
    1.2.2 邻接矩阵:是一个二维数组。是不错的一种图存储结构,但是我们也发现,对于边数相对顶点较少的图,这种结构是存在对存储空间的极大浪费的。
      正对于这两种存储结构,下一篇做详细的介绍。
    1.3 构建图:
            function Graph(v) {
                this.vertices = v;
                this.edges = 0;
                this.ajd = [];
                for(var i = 0;i < this.vertices;i++) {
                    this.ajd[i] = [];
                    this.ajd[i].push("");
                }
                this.addEdge = addEdge;
                this.toString = toString;
            }
    图的初始化,记录了一个图表示的边上的数量。用一个长度与图的顶点相同的数组记录顶点的数量。for循环是给每一个数组中的元素(顶点)创建一个子数组来存储所有相邻的顶点(链表),并将所有元素初始化为空字符串。
            function assEdge(v,w) {
                this.ajd[v].push(w);
                this.ajd[w].push(v);
                edges++;
            }
    向邻接表中添加元素。如传入A,B时。先查找顶点A的邻接表,将B添加搭配列表中,然后再查找顶点B的邻接表,将顶点A插入列表。最后边数加1。
            function showGraph() {
                for(var i = 0;i < this.vertices;i++) {
                    console.log(i+" ->");
                    for(var j = 0;j < this.vertices;j++) {
                        if(this.adj[i][j] != undefined) {
                            console.log(this.adj[i][j]+"");
                        }
                    }
                    console.log("");
                }
            } 
            //test...
            var gr = new Graph(5);
            gr.addEdge(0,1);
            gr.addEdge(0,2);
            gr.addEdge(1,3);
            gr.addEdge(2,4);
            gr.showGraph();

    完整代码:

            ~(function() {
                function Graph(v) {
                    this.vertices = v;
                    this.edges = 0;
                    this.adj = [];
                    for(var i = 0;i < this.vertices;i++) {
                        this.adj[i] = [];
                        this.adj[i].push("");
                    }
                    //this.addEdge= addEdge;
                    //this.showGraph = showGraph;
                }
                Graph.prototype.addEdge = function(v,w) {
                    this.adj[v].push(w);
                    this.adj[w].push(v);
                    this.edges++;
                };
                Graph.prototype.showGraph = function() {
                    for(var i = 0;i < this.vertices;i++) {
                        console.log(i+"--> ");
                        for(var j = 0;j < this.vertices;j++) {
                            if(this.adj[i][j] != undefined) {
                                console.log(this.adj[i][j] +"");
                            }
                        }
                    }
                };
                var gr1 = new Graph(5);
                gr1.addEdge(0,1);
                gr1.addEdge(0,2);
                gr1.addEdge(1,3);
                gr1.addEdge(2,4);
                gr1.showGraph();
            })();
    1.4 搜索图:
    从一个指定的顶点到达其他的顶点。两种基础搜索:深度优先和广度优先。
    1.4.1 深度优先搜索
    从一条路径的顶点开始追溯,知道这条路径的最后一个顶点,然后回溯,继续追溯下一条路径,直到到达最后的顶点,往复如此,直到没有路径为止。这不是在搜索特定的路径,而是通过搜索来查看在图中有哪些路径可以选择。
    算法:访问一个没有被访问过的顶点,将他标记为已访问,在递归的去访问在初始顶点的邻接表中其他没有访问过的顶点。
    此算法需要给Graph类添加一个数组用来存储已经访问过的顶点,将他的元素全部初始化为false。
            function Graph(v) {
                this.vertices = v;
                this.edges = 0;
                this.adj = [];
                for(var i = 0;i < this.vertices;i++) {
                    this.adj[i] = [];
                    this.adj[i].push(" ");
                }
                this.marked = [];
                for(var j = 0;j < this.vertices;j++) {
                    this.marked[i] = false;
                }
                this.addEdge = addEdge;
                this.showGraph = showGraph;
                this.deepFirst = deepFirst;
            }
            function addEdge(v,w) {
                this.adj[v].push(w);
                this.adj[w].push(v);
                this.edges++;
            }
            function showGraph(){
                for(var i = 0;i < this.vertices;i++) {
                    console.log(i+"-->");
                    for(var j = 0;j < this.vertices;j++) {
                        if(this.adj[i][j] != undefined) {
                            console.log(this.adj[i][j] + " ");
                        }
                    }
                }
            }
            function deepFirst(v) {
                this.marked[v] = true;
                if(this.adj[v] != undefined) {
                    console.log("访问的顶点:"+v);
                }
                for(var w in this.adj[v]) {
                    //alert(0);
                    if(!this.marked[w]) {
                        this.deepFirst(w);
                        alert(1);
                    }
                }
            }
            var gr = new Graph(5);
            gr.addEdge(0,1);
            gr.addEdge(0,2);
            gr.addEdge(1,3);
            gr.addEdge(2,4);
            gr.showGraph();
            gr.deepFirst(4);


  • 相关阅读:
    Git 码云操作
    多线程基础必要知识点!看了学习多线程事半功倍(转)
    Spring技术内幕:设计理念和整体架构概述(转)
    单例模式你会几种写法?(转)
    Linux-看完这篇Linux基本的操作就会了(转)
    每天一个linux命令9之crontab 定时任务
    在linux下给grep命令添加颜色
    springmvc使用StringHttpMessageConverter需要配置编码
    MySQL 中的 base64 函数
    spirng整合rmi
  • 原文地址:https://www.cnblogs.com/intelwisd/p/7794367.html
Copyright © 2011-2022 走看看