• 浅谈图的存储结构与遍历


    简述图的存储结构

      图的存储结构分为:邻接矩阵与邻接表

      

      邻接矩阵分为顶点、边表(1代表存在边、0代表不存在)。

      邻接链表分为顶点(顶点信息、第一个边结点)、边表(顶点序号、下一个边结点)。

      领结链表数据结构:

    public class VertexNode {
        private String vertex;
        private EdgeNode firstEdge;
    }
    //边表结点
    public class EdgeNode {
        private int edge;
        private EdgeNode next;
    }

    图的遍历原理

      遍历:深度遍历、广度遍历。

      深度遍历类似于树的前序遍历,遇见结点就访问。

      广度遍历类似于树的层序遍历,先把结点入队,当结点出队的时候,访问该节点,把该节点的邻接结点入队。

      以邻接矩阵为例分析:

      深度遍历的访问过程:

    1. 访问V0,判断V0的是否被 访问标记为true,如果为true则不继续访问。如果为false,扫描edge[0][0]—edge[0][n]。
    2. 发现edge[0][3]==1,则访问V1。按照步骤一访问,剩余的都按照这种方式继续访问。
    3. 访问顺序为V0-V1-V2-V3。

      广度遍历的访问过程:

    1. 访问结点V0,V0入队。
    2. 判断队列为空,如果不为空,队头出队即V0出队并且打印结点信息。
    3. 判断V0的边是否被访问过,若没有被访问过则全部入队,即V1、V3入队。
    4. 依次按照循环1-3步骤直到队列为空
    5. 访问顺序:V0-V1-V3-V2

    图遍历代码实现

    public interface BaseGraph {
        //深度优先遍历-类似于前序遍历
        void DFSTraverse(int v);
        //广度优先遍历-类似于层序遍历
        void BFSTraverse(int v);
    }

    邻接矩阵代码实现

    public class AdjMatrixGraph implements BaseGraph {
        public static final int MAX_SIZE=20;
        //图的顶点数
        private int vertexNum;
        //图的边数
        private int edgeNum;
    
    </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> edge[][];
    
    </span><span style="color: #0000ff;">private</span><span style="color: #000000;"> String vertex[];
    
    </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> isDFSVisited[];
    
    </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> isBFSVisited[];
    
    </span><span style="color: #008000;">/**</span><span style="color: #008000;">
     * </span><span style="color: #808080;">@param</span><span style="color: #008000;"> vertex 图的顶点
     * </span><span style="color: #808080;">@param</span><span style="color: #008000;"> n 图的顶点数
     * </span><span style="color: #808080;">@param</span><span style="color: #008000;"> e    图的边数
     </span><span style="color: #008000;">*/</span>
    <span style="color: #0000ff;">public</span> AdjMatrixGraph(String vertex[],<span style="color: #0000ff;">int</span> n,<span style="color: #0000ff;">int</span><span style="color: #000000;"> e) {
        </span><span style="color: #0000ff;">this</span>.vertexNum=<span style="color: #000000;">n;
        </span><span style="color: #0000ff;">this</span>.edgeNum=<span style="color: #000000;">e;
        isDFSVisited</span>=<span style="color: #0000ff;">new</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;">[vertexNum];
        isBFSVisited</span>=<span style="color: #0000ff;">new</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;">[vertexNum];
        </span><span style="color: #0000ff;">this</span>.edge=<span style="color: #0000ff;">new</span> <span style="color: #0000ff;">int</span><span style="color: #000000;">[vertexNum][vertexNum];
        </span><span style="color: #0000ff;">this</span>.vertex=<span style="color: #0000ff;">new</span><span style="color: #000000;"> String[vertexNum];
        </span><span style="color: #008000;">//</span><span style="color: #008000;">初始化顶点</span>
        <span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">int</span> i=0;i&lt;vertexNum;i++<span style="color: #000000;">){
            </span><span style="color: #0000ff;">this</span>.vertex[i]=<span style="color: #000000;">vertex[i];
        }
        
        </span><span style="color: #008000;">//</span><span style="color: #008000;">初始化边表</span>
        <span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">int</span> row=0;row&lt;vertexNum;row++<span style="color: #000000;">){
            </span><span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">int</span> colunmNum=0;colunmNum&lt;vertexNum;colunmNum++<span style="color: #000000;">){
                edge[row][colunmNum]</span>=0<span style="color: #000000;">;
            }
        }
        
        Scanner sc</span>=<span style="color: #0000ff;">new</span><span style="color: #000000;"> Scanner(System.in);
        </span><span style="color: #008000;">//</span><span style="color: #008000;">输入边表信息</span>
        <span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">int</span> k=0;k&lt;edgeNum;k++<span style="color: #000000;">){
            </span><span style="color: #008000;">//</span><span style="color: #008000;">领阶矩阵的行号</span>
            <span style="color: #0000ff;">int</span> rowNum=<span style="color: #000000;">sc.nextInt();
            </span><span style="color: #008000;">//</span><span style="color: #008000;">领阶矩阵的列号</span>
            <span style="color: #0000ff;">int</span> colunmNum=<span style="color: #000000;">sc.nextInt();
            edge[rowNum][colunmNum]</span>=1<span style="color: #000000;">;
            edge[colunmNum][rowNum]</span>=1<span style="color: #000000;">;
        }
    }
    
    </span><span style="color: #008000;">/**</span><span style="color: #008000;">
     * 深度优先遍历
     </span><span style="color: #008000;">*/</span><span style="color: #000000;">
    @Override
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> DFSTraverse(<span style="color: #0000ff;">int</span><span style="color: #000000;"> v) {
        System.out.print(vertex[v]</span>+"	"<span style="color: #000000;">);
        isDFSVisited[v]</span>=<span style="color: #0000ff;">true</span><span style="color: #000000;">;
        </span><span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">int</span> j=0;j&lt;vertexNum;j++<span style="color: #000000;">){
            </span><span style="color: #0000ff;">if</span>(edge[v][j]==1&amp;&amp;isDFSVisited[j]==<span style="color: #0000ff;">false</span><span style="color: #000000;">){
                DFSTraverse(j);
            }
        }
    }
    
    </span><span style="color: #008000;">/**</span><span style="color: #008000;">
     * 广(宽)度优先遍历
     </span><span style="color: #008000;">*/</span><span style="color: #000000;">
    @Override
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> BFSTraverse(<span style="color: #0000ff;">int</span><span style="color: #000000;"> v) {
        Queue</span>&lt;Integer&gt; queue=<span style="color: #0000ff;">new</span> LinkedList&lt;Integer&gt;<span style="color: #000000;">();
        System.out.print(vertex[v]</span>+"	"<span style="color: #000000;">);
        isBFSVisited[v]</span>=<span style="color: #0000ff;">true</span><span style="color: #000000;">;
        queue.add(v);
        </span><span style="color: #0000ff;">while</span>(!<span style="color: #000000;">queue.isEmpty()){
            v</span>=<span style="color: #000000;">queue.poll();
            </span><span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">int</span> j=0;j&lt;vertexNum;j++<span style="color: #000000;">){
                </span><span style="color: #0000ff;">if</span>(edge[v][j]==1&amp;&amp;isBFSVisited[j]==<span style="color: #0000ff;">false</span><span style="color: #000000;">){
                    System.out.print(vertex[j]</span>+"	"<span style="color: #000000;">);
                    isBFSVisited[j]</span>=<span style="color: #0000ff;">true</span><span style="color: #000000;">;
                    queue.add(j);
                }
            }
        }
    }
    
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) {
        String [] vertex</span>=<span style="color: #0000ff;">new</span> String[]{"vo","v1","v2","v3"<span style="color: #000000;">};
        AdjMatrixGraph graph</span>=<span style="color: #0000ff;">new</span> AdjMatrixGraph(vertex, 4, 4<span style="color: #000000;">);
        </span><span style="color: #008000;">//</span><span style="color: #008000;">图的深度遍历</span>
        System.out.println("图的深度遍历"<span style="color: #000000;">);
        graph.DFSTraverse(</span>0<span style="color: #000000;">);
        </span><span style="color: #008000;">//</span><span style="color: #008000;">图的广度遍历</span>
        System.out.println(""<span style="color: #000000;">);
        System.out.println(</span>"图的广度遍历"<span style="color: #000000;">);
        graph.BFSTraverse(</span>0<span style="color: #000000;">);
    }
    

    }

     

    邻接表代码实现

    public class AdjListGraph implements BaseGraph{
    
    </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> vertexNum;
    </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">int</span><span style="color: #000000;"> edgeNum;
    </span><span style="color: #0000ff;">private</span><span style="color: #000000;"> VertexNode [] adjList;
    </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> isDFSVisited[];
    </span><span style="color: #0000ff;">private</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;"> isBFSVisited[];
    
    </span><span style="color: #0000ff;">public</span> AdjListGraph(String vertexs[],<span style="color: #0000ff;">int</span> vertexNum,<span style="color: #0000ff;">int</span><span style="color: #000000;"> edgeNum) {
        </span><span style="color: #0000ff;">this</span>.vertexNum=<span style="color: #000000;">vertexNum;
        </span><span style="color: #0000ff;">this</span>.edgeNum=<span style="color: #000000;">edgeNum;
        adjList</span>=<span style="color: #0000ff;">new</span><span style="color: #000000;"> VertexNode[vertexNum];
        isDFSVisited</span>=<span style="color: #0000ff;">new</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;">[vertexNum];
        isBFSVisited</span>=<span style="color: #0000ff;">new</span> <span style="color: #0000ff;">boolean</span><span style="color: #000000;">[vertexNum];
        </span><span style="color: #008000;">//</span><span style="color: #008000;">初始化</span>
        <span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">int</span> i=0;i&lt;vertexNum;i++<span style="color: #000000;">){
            adjList[i]</span>=<span style="color: #0000ff;">new</span><span style="color: #000000;"> VertexNode();
            adjList[i].setVertex(vertexs[i]);
            adjList[i].setFirstEdge(</span><span style="color: #0000ff;">null</span><span style="color: #000000;">);
        }
        
        Scanner sc</span>=<span style="color: #0000ff;">new</span><span style="color: #000000;"> Scanner(System.in);
        </span><span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">int</span> k=0;k&lt;edgeNum;k++<span style="color: #000000;">){
            </span><span style="color: #0000ff;">int</span> i=sc.nextInt();<span style="color: #008000;">//</span><span style="color: #008000;">第几号节点</span>
            <span style="color: #0000ff;">int</span> j=sc.nextInt();<span style="color: #008000;">//</span><span style="color: #008000;">链接边节点</span>
            EdgeNode eNode=<span style="color: #0000ff;">new</span><span style="color: #000000;"> EdgeNode(j,adjList[i].getFirstEdge());
            adjList[i].setFirstEdge(eNode);
        }
    }
    
    @Override
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> DFSTraverse(<span style="color: #0000ff;">int</span><span style="color: #000000;"> v) {
        System.out.println(adjList[v].getVertex());
        isDFSVisited[v]</span>=<span style="color: #0000ff;">true</span><span style="color: #000000;">;
        EdgeNode p</span>=<span style="color: #000000;">adjList[v].getFirstEdge();
        </span><span style="color: #0000ff;">while</span>(p!=<span style="color: #0000ff;">null</span><span style="color: #000000;">){
            </span><span style="color: #0000ff;">int</span> j=<span style="color: #000000;">p.getEdge();
            </span><span style="color: #0000ff;">if</span>(isDFSVisited[j]==<span style="color: #0000ff;">false</span><span style="color: #000000;">)
                DFSTraverse(j);
            p</span>=<span style="color: #000000;">p.getNext();
        }
    }
    
    @Override
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">void</span> BFSTraverse(<span style="color: #0000ff;">int</span><span style="color: #000000;"> v) {
        Queue</span>&lt;Integer&gt; queue=<span style="color: #0000ff;">new</span> LinkedList&lt;Integer&gt;<span style="color: #000000;">();
        System.out.println(adjList[v].getVertex());
        isBFSVisited[v]</span>=<span style="color: #0000ff;">true</span><span style="color: #000000;">;
        queue.add(v);
        </span><span style="color: #0000ff;">while</span>(!<span style="color: #000000;">queue.isEmpty()){
            v</span>=<span style="color: #000000;">queue.poll();
            EdgeNode p</span>=<span style="color: #000000;">adjList[v].getFirstEdge();
            </span><span style="color: #0000ff;">while</span>(p!=<span style="color: #0000ff;">null</span><span style="color: #000000;">){
                </span><span style="color: #0000ff;">int</span> j=<span style="color: #000000;">p.getEdge();
                </span><span style="color: #0000ff;">if</span>(isBFSVisited[j]==<span style="color: #0000ff;">false</span><span style="color: #000000;">){
                    System.out.println(adjList[j].getVertex());
                    isBFSVisited[j]</span>=<span style="color: #0000ff;">true</span><span style="color: #000000;">;
                    queue.add(j);
                }
                p</span>=<span style="color: #000000;">p.getNext();
            }
        }
    }
    
    </span><span style="color: #0000ff;">public</span> <span style="color: #0000ff;">static</span> <span style="color: #0000ff;">void</span><span style="color: #000000;"> main(String[] args) {
        String [] vertexs</span>=<span style="color: #0000ff;">new</span> String[]{"vo","v1","v2","v3"<span style="color: #000000;">};
        AdjListGraph graph</span>=<span style="color: #0000ff;">new</span> AdjListGraph(vertexs, 4,4<span style="color: #000000;">);
        graph.DFSTraverse(</span>0<span style="color: #000000;">);
        graph.BFSTraverse(</span>0<span style="color: #000000;">);
    }
    

    }

  • 相关阅读:
    爬虫的基本原理、requests模块、模拟登陆网站、爬取视频网站、cookie池和代理池、正向代理和反向代理
    git初识、
    签发token、校验token、多方式登录签发token的实现、自定义认证反爬规则的认证类、admin使用自定义User表:新增用户密码密文、群查接口各种筛选组件数据准备、drf搜索过滤组件、drf排序过滤组件、drf基础分页组件
    频率认证源码分析、自定义频率认证组件、JWT认证、drf-jwt插件
    auth组件的权限六表 自定义User的权限六表 六表之间的数据访问 三大认证整体源码分析 自定义认证类 系统权限类 自定义权限类
    视图类与序列化类传参、二次封装response类、视图家族、GenericAPIView视图基类、mixins视图6大工具类、generic中的工具视图、视图集、GenericAPIView 与 APIView 作为两大继承视图的区别、工具视图集、路由组件(了解)
    修改文件后缀
    python统计自己微信好友并抓取信息
    关于今日头条小程序(字节跳动小程序)相关问题
    关于飞鱼文档不详细无法拉取数据问题
  • 原文地址:https://www.cnblogs.com/qiuyong/p/6842781.html
Copyright © 2020-2023  润新知