zoukankan      html  css  js  c++  java
  • 图由顶点和边 组成的一种结构G=(V,E )

    图的存储结构 (邻接矩阵)

    图的遍历

    深度优先算法

    随便走,等到无路可走,退回重新走,直到图被遍历完。

    /*
     * 定义图的结构
     */
    public class Graph {
        //节点数目
        protected int size;
        //定义数组,保存顶点信息
        protected String[] nodes;
    
        //定义矩阵保存顶点信息
        protected int[][] edges;
    
        /**
         *      A B C D E F G
         *   A  0 0 1 1 0 1 0
         *   B  0 0 1 0 0 0 0
         *   C  1 1 0 1 0 0 0
         *   D  1 0 1 0 0 0 0
         *   E  0 0 0 0 0 0 1
         *   F  1 0 0 0 0 0 1
         *   G  0 0 0 0 1 1 0
         */
        public Graph(){
            //初始化顶点
            nodes = new String[]{"A","B","C","D","E","F","G"};
            size=nodes.length;
    
            //初始化边---- 为了直观,做一个常量定义
            final int A=0,B=1,C=2,D=3,E=4,F=5,G=6;
            edges = new int[size][size];
            edges[A][C] = 1;
            edges[A][D] = 1;
            edges[A][F] = 1;
            edges[B][C] = 1;
            edges[C][A] = 1;
            edges[C][D] = 1;
            edges[C][B] = 1;
            edges[D][A] = 1;
            edges[D][C] = 1;
            edges[E][G] = 1;
            edges[F][A] = 1;
            edges[F][G] = 1;
            edges[G][F] = 1;
            edges[G][E] = 1;
        }
    }
     private int[] visit = new int[size];     //遍历标志,防止死环遍历
    
        /**
         * 深度优先遍历
         * 一条路走到黑,不撞南墙不回头
         * 对每一个可能的分支路径深入到不能再深入为止
         */
        public void DeepFirst(int start) {//从第n个节点开始遍历
    
            visit[start] = 1;              //标记为1表示该顶点已经被处理过
            System.out.println("齐天大圣到—>" + this.nodes[start]+"一游"); //输出节点数据
    
            for (int i=0;i<this.size;i++){
                if (this.edges[start][i] == 1 && visit[i]==0){
                    //邻接点
                    DeepFirst(i);
                }
            }
    
        }
    

    广度优先算法

    访问节点所有可以到达的节点,再把访问到的节点的临界节点都找出来

        /**
         * 广度优先遍历
         * 广度优先搜索遍历图的过程中以v 为起始点,由近至远,
         * 依次访问和v 有路径相通且路径长度为1,2,…的顶点
         * 第一批节点的邻接点,?
         */
        private int[] queue = new int[size];
        public void BreadthFirst(int front,int tail) {
            int last = tail;
    
            for (int index=front;index<=tail;index++){
                int node = queue[index];
    
                System.out.println("齐天大圣到—>" + this.nodes[node]+"一游"); //输出节点数据
                //找出所有的邻接点
                for (int i=0;i<this.size;i++){
                    if (this.edges[node][i] == 1 && visit[i]==0){
                        //邻接点
                        visit[i] = 1;
                        queue[++last] = i;
    
                    }
                }
            }
    
            //遍历下一批节点
            if (last > tail){
                BreadthFirst(tail+1,last);
            }
    
        }
    
        public void BreadthFirst(int start){
            queue[0] = start;
            visit[start] = 1;
            BreadthFirst(0,0);
        }
    
        public static void main(String[] args) {
            GraphCover graph = new GraphCover();
    
            graph.BreadthFirst(0);
        }
    }
    

    找出图中最短路径

    得到图的最短路径树

    迪杰斯特拉算法 Dijkstra

    扩展知识

    int i = Integer.Max_VALUE;

    i= Integer.MAX_VALUE ,即 i = 2147483647,i再加1,就变成了-2147483648

    package com.enjoy.graph;
    
    public class Dijkstra {
       //节点数目
       protected int size;
       //定义数组,保存顶点信息
       protected String[] nodes;
    
       //定义矩阵保存顶点信息
       protected int[][] edges;
    
       private int[] isMarked;//节点确认--中心标识
       private String[] path;//源到节点的路径信息
       private int[] distances;//源到节点的距离
    
       public Dijkstra(){
          init();
    
          isMarked = new int[size];
          path = new String[size];
          distances = new int[size];
    
          for (int i=0;i<size;i++){
             path[i] = "";
             distances[i] = Integer.MAX_VALUE;
          }
       }
    
       public static void main(String[] args) {
          Dijkstra dijkstra = new Dijkstra();
          dijkstra.search(3);
       }
    
       public void search(int node){
          path[node] = nodes[node];
          distances[node] = 0;
    
          do {
             flushlast(node);
             node = getShort();
          }while (node != -1);
       }
    
       //1、扫描AA邻接点,记录邻接点权重值
       private void flushlast(int node){
          isMarked[node] = 1;
          System.out.println(path[node]);
          //扫描邻接点
          for (int i=0;i<size;i++){
             if (this.edges[node][i] > 0){
                //计算AA节点到 i节点的权重值
                int distant = distances[node] + this.edges[node][i];
                if (distant < distances[i]){
                   distances[i] = distant;
                   path[i] = path[node] +"-->"+ nodes[i];
                }
             }
          }
       }
    
    // 2、找出邻接点里最小的那个值
       private int getShort(){
          int last = -1;
    
          int min = Integer.MAX_VALUE;
          for (int i=0;i<size;i++){
    
             if (isMarked[i] == 1){
                continue;
             }
    
             if (distances[i] < min){
                min = distances[i];
                last = i;
             }
          }
    
          return last;
       }
    
    
       public void init(){
          //初始化顶点
          nodes = new String[]{"AA","A","B","C","D","E","F","G","H","M","K","N"};
          //节点编号-常量
          final int AA=0,A=1,B=2,C=3,D=4,E=5,F=6,G=7,H=8,M=9,K=10,N=11;
          size=nodes.length;
    
          edges = new int[size][size];
          edges[AA][A] = 3;
          edges[AA][B] = 2;
          edges[AA][C] = 5;
          edges[A][AA] = 3;
          edges[A][D] = 4;
          edges[B][AA] = 2;
          edges[B][C] = 2;
          edges[B][G] = 2;
          edges[B][E] = 3;
          edges[C][AA] = 5;
          edges[C][E] = 2;
          edges[C][B] = 2;
          edges[C][F] = 3;
          edges[D][A] = 4;
          edges[D][G] = 1;
          edges[E][B] = 3;
          edges[E][C] = 2;
          edges[E][F] = 2;
          edges[E][K] = 1;
          edges[E][H] = 3;
          edges[E][M] = 1;
          edges[F][C] = 3;
          edges[F][E] = 2;
          edges[F][K] = 4;
          edges[G][B] = 2;
          edges[G][D] = 1;
          edges[G][H] = 2;
          edges[H][G] = 2;
          edges[H][E] = 3;
          edges[K][E] = 1;
          edges[K][F] = 4;
          edges[K][N] = 2;
          edges[M][E] = 1;
          edges[M][N] = 3;
          edges[N][K] = 2;
          edges[N][M] = 3;
       }
    
    }
    

    工程施工图

    • 发动机为关键节点(工程完成的时间取决于发动机节点完成的时间)

    • 这种依赖图不能出现循环

    分析图的依赖的问题,解决依赖问题

    package com.enjoy.graph;
    
    import java.util.Stack;
    
    public class Aov {
       //节点数目
       protected int size;
       //定义数组,保存顶点信息
       protected String[] nodes;
    
       //定义矩阵保存顶点信息
       protected int[][] edges;
    
       public Aov(){
          init();
       }
    
       //入度数组
       private int[] eSize;
       private int[] fast;//最早时间
       private int[] last;//最晚时间
       public static void main(String[] args) {
          Aov aov = new Aov();
          aov.flush();
    //    int[] path = aov.getPath();
          aov.exeKey();
       }
    
       public void exeKey(){
          int[] path = getPath();
          int start = path[0],end = path[size-1];
    
          exeFast(start);
    
          for (int i=0;i<size;i++){//初始化成工程最大值
             last[i] = fast[end];
          }
          exeLast(end);
    
          for (int i=0;i<size;i++){
             int node = path[i];
             if (fast[node] == last[node]){
                System.out.print("--->"+nodes[node]);
             }
          }
    
          System.out.println();
       }
    
    
       private void exeFast(int node){
          for (int i=0;i<size;i++){
             if (this.edges[node][i] > 0){
                int cost = fast[node] + this.edges[node][i];
                if (cost > fast[i]){
                   fast[i] = cost;
                   exeFast(i);
                }
             }
          }
       }
    
       private void exeLast(int node){
          for (int i=0;i<size;i++){
             if (this.edges[i][node] > 0){
                int cost = last[node] - this.edges[i][node];
                if (cost < last[i]){
                   last[i] = cost;
                   exeLast(i);
                }
             }
          }
       }
    
    
       //1、计算出各个节点的入度
       private void flush(){
          eSize = new int[size];
    
          for (int node=0;node<size;node++){
             for (int i=0;i<size;i++){
                if (edges[i][node] > 0){
                   eSize[node]++;
                }
             }
          }
       }
    
       private int[] getPath(){
          int count = 0;
          int[] path = new int[size];
    
          // 2、入度为0节点入队
    //    Queue<Integer> queue = new LinkedList<>();
          Stack<Integer> stack = new Stack<>();
          for (int i=0;i<size;i++){
             if (eSize[i] == 0){
    //          queue.offer(i);
                stack.push(i);
             }
          }
    
          // 3、入队节点的邻接点入度-1
          while (!stack.empty()){
             Integer node = stack.pop();
    
    //       System.out.print("---->"+nodes[node]);
             path[count++] = node;
    
             for (int i=0;i<size;i++){
                if (this.edges[node][i] > 0){
                   eSize[i]-- ;
                   if (eSize[i] == 0){
    //                queue.offer(i);
                      stack.push(i);
                   }
                }
             }
          }
    
    
          return path;
       }
    
    
    
    
       public void init(){
          //初始化顶点
          nodes = new String[]{"AA","A","B","C","D","E","F","G","H","M","K","N"};
          //节点编号-常量
          final int AA=0,A=1,B=2,C=3,D=4,E=5,F=6,G=7,H=8,M=9,K=10,N=11;
          size=nodes.length;
    
          fast = new int[size];
          last = new int[size];
    
          edges = new int[size][size];
          edges[AA][A] = 3;
          edges[AA][B] = 2;
          edges[AA][C] = 5;
          edges[A][D] = 4;
          edges[B][G] = 2;
          edges[B][E] = 3;
          edges[C][E] = 2;
          edges[C][F] = 3;
          edges[D][G] = 1;
          edges[E][K] = 1;
          edges[E][M] = 8;
          edges[F][K] = 4;
          edges[G][H] = 2;
          edges[H][M] = 3;
          edges[K][N] = 2;
          edges[M][N] = 3;
       }
    }
    

    关键路径

  • 相关阅读:
    查看JAVA占用CPU高的线程日志
    行为面试法(STAR)
    下载mysql document
    win10 子系统ubuntu中文乱码
    java 排序
    进制
    开始转型学习java
    java Collections工具类
    java Map实例
    java Map
  • 原文地址:https://www.cnblogs.com/AronJudge/p/14509129.html
Copyright © 2011-2022 走看看