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;
       }
    }
    

    关键路径

  • 相关阅读:
    26 转义符 re模块 方法 random模块 collection模块的Counter方法
    25 正则表达式
    24 from 模块 import 名字
    24 from 模块 import 名字
    24 from 模块 import 名字
    23 析构方法 items系列 hash方法 eq方法
    21 isinstance issubclass 反射 _str_ _new_ _len_ _call_
    20 属性, 类方法, 静态方法. python2与python3的区别.
    python(1)
    python之字符串格式化
  • 原文地址:https://www.cnblogs.com/AronJudge/p/14509129.html
Copyright © 2011-2022 走看看