数据结构基本整理(图)

基础

深度优先遍历


    /**
     * 深度优先遍历(仅针对一个节点的深度优先)
     * 当前点输出且设置为以访问
     * 寻找下一个未被访问的点,输出 ,寻找下一个点
     * 到达最深处时,会自动回溯,for循环寻找父级的同层次可访问节点
     *
     * @param p
     * @param graph
     */
    public static void depthTraverse(int p, int[][] graph) {
        boolean[] visited = new boolean[graph.length];
        System.out.println(p);
        visited[p] = true;
        depth(graph, p, visited);
    }

    public static void depth(int[][] graph, int p, boolean[] visited) {
        for (int i = 0; i < graph[p].length; i++) {
            if (graph[p][i] > 0 && !visited[i]) {
                System.out.println(i);
                visited[i] = true;
                depth(graph, i, visited);
            }
        }
    }

广度优先遍历

  /**
     * 广度优先遍历(仅针对一个顶点)
     * 像队列中添加元素时,旧需要设置其未已访问,否则会出现重复
     * (如队列中 2,3,4;读取2时,可到达4,则队列中会存两个4)
     *
     * @param p     p
     * @param graph 图
     * @return
     * @createTime 2020年04月15日
     * @author: wangfeifan
     */
    public static void breadthTraverse(int p, int[][] graph) {
        LinkedList<Integer> queue = new LinkedList<>();
        boolean[] visited = new boolean[graph.length];
        queue.add(p);
        visited[p] = true;
        while (!queue.isEmpty()) {
            p = queue.poll();
            System.out.println(p);
            for (int i = 0; i < graph[p].length; i++) {
                if (!visited[i] && graph[p][i] == 1) {
                    queue.add(i);
                    visited[i] = true;
                }
            }
        }
    }

最小生成树

  1. 最小生成树,为带权无向图中,使每一个顶点都连通的最小权值和(仅边最小,而非从顶点到某一终点的最小)
  2. 最小生成树唯一(除非存在权值相同情况)
  3. mst性质:顶点v的真子集 tv 到 v-tv的所有边中权值最小的边,一定在最小生成树中

Prim 算法

  1. 过程:

    1. 默认起点 p
    2. 初始 tv 集合中仅含p,然后不断扩展tv集合,得到新的权值最小的边
    3. 先得到边集合中的最小值,然后遍历新顶点边集合,得到所有边中最小边
    4. 遍历时判断时候替换终点边(保持编辑和中存储的为起点集合到对应终点的最小值)
    5. 需要重复 n-1次,代码中,通过map中值的数量来保证迭代次数
  2. 注意:

    1. 替换权值最小边时,可以为0-3,值28,被2-3,值20所替换,并为要求从零开始;
    2. 替换时,边值的比较也仅仅为两条边单纯比较,而非0-2-3的总值为20
 /**
     * 边值中,不可达存储为最大值 不要使用-1
     *
     * 最小生成树,(针对某一个具体节点)
     * 根据最小生树性质 :顶点v的真子集 tv 到 v-tv的所有边中权值最小的边,一定在最小生成树中
     * 初始 tv 集合中仅含p,然后不断扩展tv集合,得到新的权值最小的边
     * 先得到边集合中的最小值,然后遍历新顶点边集合,得到最小边,
     * 遍历时判断时候替换终点边(保持编辑和中存储的为起点集合到对应终点的最小值)
     *
     *
     * map 存储边,初始添加n-1的顶点,确定顶点后,从map中移除
     * 已确定的顶点添加对应标记,防止重复边
     * @param graph 图
     * @param p     p
     * @return
     * @createTime 2020年04月16日
     * @author: wangfeifan
     */
    public static void Prim(int[][] graph, int p) {
        System.out.println(p);
        boolean[] visited = new boolean[graph.length];
        Map<Integer, Integer> weight = new HashMap<>();

        visited[p] = true;
        int min = p;
        int minWeight = Integer.MAX_VALUE;

        for (int i = 0; i < graph[p].length; i++) {
            if (i != p) {
                if (graph[p][i] == -1) {
                    graph[p][i] = Integer.MAX_VALUE;
                }
                weight.put(i, graph[p][i]);
                if (graph[p][i] < minWeight) {
                    min = i;
                    minWeight = graph[p][i];
                }
            }
        }
        System.out.println(min);
        weight.remove(min);
        visited[min] = true;
        while (!weight.isEmpty()) {
            p = min;
            minWeight = Integer.MAX_VALUE;
            for (Map.Entry<Integer, Integer> entry : weight.entrySet()) {
                if (entry.getValue() < minWeight) {
                    minWeight = entry.getValue();
                    min = entry.getKey();
                }
            }
            for (int i = 0; i < graph[p].length; i++) {
                if (graph[p][i] == -1) {
                    graph[p][i] = Integer.MAX_VALUE;
                }

                if (!visited[i]) {
                    if(weight.getOrDefault(i,0)>graph[p][i]){
                        weight.put(i,graph[p][i]);
                    }
                    if (i != p && graph[p][i] < minWeight) {
                        minWeight = graph[p][i];
                        min = i;
                    }

                }
            }
            System.out.println(min);
            weight.remove(min);
            visited[min] = true;
        }
    }

Kruskal算法

  1. 每一步选择权值最小且不产生回路的边

最短路径

单源最短路径(Dijkstra 算法)

  1. 概念:
    1. 从顶点p 开始 ,确定到其他顶点的最短路路径
    2. 判断n-1次,每次可以确定一条边(从p 到其他顶点的所有边中选择最小)
  2. 过程:
    1. 初始化顶点p到其他顶点的边的权值 ,(可以唯一确定一个顶点v,不会存在如p-s-v更短的情况)
    2. 确定v后,从p到其他顶点 ; p通过v到其他顶点的所有边中,取最小边(判断新的边时,可以判断是否更新对应顶点的旧值,减少所需要判断的边数)
    3. 重复2 n- 1次
 /**
     * 从起点开始,每次确定一条边(不存在 a-b-c 比a-c小的情况 ,会先比较a-b 和a-c),每次可以唯一确定一个顶点
     * 
     * map 存储 key:顶点  value:边权重(value不断迭代,保证起点p到对应顶点值最小)
     * map 不删除值,判断点前集合中最小时,通过visited数据 判断是否参与计算
     *
     *判断顶点到其它边最小值时,先判断当前集合,在判断新增顶点产生的新边(同时迭代旧值,保证起点到对应顶点值最小,已确定顶点不参与迭代)
     * @param graph 图
     * @param p     p
     * @return
     * @createTime 2020年04月16日
     * @author: wangfeifan
     */
    public static void dijkstra(int[][] graph, int p) {
        Map<Integer, Integer> weight = new HashMap<>();
        boolean[] visited = new boolean[graph.length];
        visited[p] = true;
        System.out.println(p);

        int min = p;
        int minWeight = Integer.MAX_VALUE;
        for (int i = 0; i < graph[p].length; i++) {
            if (!visited[i]) {
                weight.put(i, graph[p][i]);
                if (graph[p][i] < minWeight) {
                    min = i;
                    minWeight = graph[p][i];
                }
            }
        }

        for (int j = 0; j < graph.length - 1; j++) {
            p = min;
            System.out.println(p);
            visited[p] = true;

            minWeight = Integer.MAX_VALUE;
            for (Map.Entry<Integer, Integer> entry : weight.entrySet()) {
                //已确定的顶点,对应边不参与计算
                if (!visited[entry.getKey()]) {
                    if (entry.getValue() < minWeight) {
                        min = entry.getKey();
                        minWeight = entry.getValue();
                    }
                }
            }
            for (int i = 0; i < graph[p].length; i++) {
                if (!visited[i]) {
                    //避免溢出
                    int temp = weight.get(p) + graph[p][i];
                    if (temp < weight.get(i)) {
                        weight.put(i, temp);
                        if (temp < minWeight) {
                            min = i;
                            minWeight = temp;
                        }
                    }
                }
            }

        }
    }

多源最短路径(Floyd 算法)

  1. 概念:
    1. 图中每个节点到其他节点的最短路径
  2. 过程:
    1. 使用两个矩阵,一个存储边的权重 w,另一个两个节点访问路径的除终点的最后一个节点 p
    2. p 中,本身,不可达位置 赋值-1;如ab形式,则赋值a;
    3. 依次使用图中的每一个节点v ,对w进行松弛,根据iv+vj和ij的值,判断是否更新,更新p时,p对应的值应该是从v到j的路径中最后一个节点的值,对应为p[v][j];

    /**
     * 多源最短路径求解
     * 构建权重矩阵,一次插入每个节点进行松弛,根据距离判断是否需要加入新的节点
     * 三重循环 一层 为插入节点 ,二层起点 三层终点
     * 插入节点位置为终点前的一个节点
     * 
     * 
     * 使用point 来保存节点顺序 ,更新时,气质应该为 point中 插入节点到终点的最近一个坐标,而非直接插入节点
     *
     * @param graph 图
     * @return
     * @createTime 2020年04月16日
     * @author: wangfeifan
     */
    public static void floyd(int[][] graph) {
        int[][] point = new int[graph.length][graph.length];
        for (int i = 0; i < graph.length; i++) {
            for (int j = 0; j < graph.length; j++) {
                if (i == j) {
                    point[i][j] = -1;
                    continue;
                }
                if (graph[i][j] == 9999) {
                    point[i][j] = -1;
                    continue;
                }
                point[i][j] = i;
            }
        }
        //经过节点
        for (int v = 0; v < graph.length; v++) {
            //起始节点
            for (int i = 0; i < graph.length; i++) {
                //终节点
                for (int j = 0; j < graph.length; j++) {
                    if (graph[i][v] + graph[v][j] < graph[i][j]) {
                        graph[i][j] = graph[i][v] + graph[v][j];
                        // 使用point
                        point[i][j] = point[v][j];
                    }
                }
            }
        }
        for (int i = 0; i < graph.length; i++) {
            for (int j = 0; j < graph.length; j++) {
                if (i != j) {
                    StringBuilder builder = new StringBuilder();
                    int p = point[i][j];
                    builder.append(j);
                    while (p != -1) {
                        builder.append(p);
                        p = point[i][p];
                    }
                    System.out.println(builder.reverse().toString());
                }
            }
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
信息数据从传统到当代,是一直在变革当中,突如其来的互联网让传统的信息管理看到了革命性的曙光,因为传统信息管理从时效性,还是安全性,还是可操作性等各个方面来讲,遇到了互联网时代才发现能补上自古以来的短板,有效的提升管理的效率和业务水平。传统的管理模式,时间越久管理的内容越多,也需要更多的人来对数据进行整理,并且数据的汇总查询方面效率也是极其的低下,并且数据安全方面永远不会保证安全性能。结合数据内容管理的种种缺点,在互联网时代都可以得到有效的补充。结合先进的互联网技术,开发符合需求的软件,让数据内容管理不管是从录入的及时性,查看的及时性还是汇总分析的及时性,都能让正确率达到最高,管理更加的科学和便捷。本次开发的医院后台管理系统实现了病房管理、病例管理、处方管理、字典管理、公告信息管理、患者管理、药品管理、医生管理、预约医生管理、住院管理、管理员管理等功能。系统用到了关系型数据库中王者MySql作为系统的数据库,有效的对数据进行安全的存储,有效的备份,对数据可靠性方面得到了保证。并且程序也具备程序需求的所有功能,使得操作性还是安全性都大大提高,让医院后台管理系统更能从理念走到现实,确确实实的让人们提升信息处理效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值