图基础算法

本文参考了 黑马程序员的算法,地址: https://www.bilibili.com/video/BV1rv4y1H7o6?p=76&spm_id_from=pageDriver&vd_source=0af94caf33fbb7a6f7ddfcf5e8c205f4

1.图的基本表示

import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class Edge {

    private Vertex linked;
    private int weight;

    public Edge(Vertex linked) {
        this(linked, 1);
    }

    public Edge(Vertex linked, int weight) {
        this.linked = linked;
        this.weight = weight;
    }
}

import lombok.Getter;
import lombok.Setter;

import java.util.List;

/**
 * @author laihaonan
 * @version 1.0
 * @description TODO
 * @date 2024/1/24 7:36 上午
 */
@Getter
@Setter
public class Vertex {

    private String name;
    private List<Edge> edges;
    private boolean isVisited;
    private Vertex pre;
    private int inDegree;
    private int dist = Integer.MAX_VALUE;

    public Vertex(String name) {
        this.name = name;
    }
}

2.图的dfs遍历

    /**
     *              b   e
     *          a   c       g
     *              d   f
     * @return
     */
     public static void dfsStack(Vertex vertex, List<String> res) {
        LinkedList<Vertex> stack = new LinkedList();
        stack.push(vertex);
        while (!stack.isEmpty()) {
            Vertex pop = stack.pop();
            pop.setVisited(true);
            res.add(pop.getName());
            if (CollectionUtil.isNotEmpty(pop.getEdges())) {
                for (Edge edge : CollectionUtil.reverse(pop.getEdges())) {
                    if (!edge.getLinked().isVisited()) {
                        stack.push(edge.getLinked());
                    }
                }
            }
        }
    }

    private static void dfs(Vertex vertex, List<String> res) {
        vertex.setVisited(true);
        res.add(vertex.getName());
        if (CollectionUtil.isNotEmpty(vertex.getEdges())) {
            for (Edge edge : vertex.getEdges()) {
                if (!edge.getLinked().isVisited()) {
                    dfs(edge.getLinked(), res);
                }
            }
        }
    }

    private static Vertex initData() {
        Vertex a = new Vertex("a");
        Vertex b = new Vertex("b");
        Vertex c = new Vertex("c");
        Vertex d = new Vertex("d");
        Vertex e = new Vertex("e");
        Vertex f = new Vertex("f");
        Vertex g = new Vertex("g");

        Edge edgeb = new Edge(b);
        Edge edgec = new Edge(c);
        Edge edged = new Edge(d);
        Edge edgee = new Edge(e);
        Edge edgef = new Edge(f);
        Edge edgeg = new Edge(g);

        List<Edge> list = new ArrayList<>();
        list.add(edgeb);
        list.add(edgec);
        list.add(edged);
        a.setEdges(list);

        List<Edge> list2 = new ArrayList<>();
        list2.add(edgee);
        b.setEdges(list2);

        List<Edge> list3 = new ArrayList<>();
        list3.add(edgeg);
        c.setEdges(list3);

        List<Edge> list4 = new ArrayList<>();
        list4.add(edgef);
        d.setEdges(list4);

        List<Edge> list5 = new ArrayList<>();
        list5.add(edgeg);
        f.setEdges(list5);

        List<Edge> list6 = new ArrayList<>();
        list6.add(edgeg);
        e.setEdges(list6);
        return a;
    }

3.图的广度遍历

public static void bfsQueue(Vertex vertex, List<String> res) {
        LinkedList<Vertex> queue = new LinkedList<>();
        queue.offer(vertex);
        vertex.setVisited(true);
        while (!queue.isEmpty()) {
            Vertex poll = queue.poll();
            res.add(poll.getName());
            if (CollectionUtil.isNotEmpty(poll.getEdges())) {
                for (Edge edge : poll.getEdges()) {
                    if (!edge.getLinked().isVisited()) {
                        queue.offer(edge.getLinked());
                        edge.getLinked().setVisited(true);
                    }
                }
            }
        }
    }

4.拓扑排序以及是否有环

public static List<Vertex> topoSort(List<Vertex> graph) {
        // 1.统计每个节点的度
        for (Vertex v : graph) {
            if (CollectionUtil.isNotEmpty(v.getEdges())) {
                for (Edge edge: v.getEdges()) {
                    edge.getLinked().setInDegree(edge.getLinked().getInDegree() + 1);
                }
            }
        }
        for (Vertex vertex : graph) {
            System.out.print(vertex.getName() + ":" + vertex.getInDegree() + ";");
        }
        System.out.println("");

        // 2.将入度=0的顶点加入队列
        LinkedList<Vertex> queue = new LinkedList<>();
        for (Vertex vertex : graph) {
            if (vertex.getInDegree() == 0) {
                queue.offer(vertex);
            }
        }
        // 3.队列不断移除顶点,每移除一个顶点,将相关顶点入度-1,若入度=0,则将顶点入队
        List<Vertex> vertices = new ArrayList<>();
        while(!queue.isEmpty()) {
            Vertex poll = queue.poll();
            vertices.add(poll);
            if (CollectionUtil.isNotEmpty(poll.getEdges())) {
                for (Edge edge : poll.getEdges()) {
                    edge.getLinked().setInDegree(edge.getLinked().getInDegree() - 1);
                    if (edge.getLinked().getInDegree() == 0) {
                        queue.offer(edge.getLinked());
                    }
                }
            }
        }
        return vertices;
    }

    public static boolean isLooop(List<Vertex> graph) {
        List<Vertex> topoSortRes = topoSort(graph);
        return topoSortRes.size() != graph.size();
    }

    private static List<Vertex> initData() {
        List<Vertex> graph = new ArrayList<>();

        Vertex a = new Vertex("a");
        Vertex b = new Vertex("b");
        Vertex c = new Vertex("c");
        Vertex d = new Vertex("d");
        Vertex e = new Vertex("e");
        Vertex f = new Vertex("f");
        Vertex g = new Vertex("g");

        graph.add(a);
        graph.add(b);
        graph.add(c);
        graph.add(d);
        graph.add(e);
        graph.add(f);
        graph.add(g);

        Edge edgeb = new Edge(b);
        Edge edgec = new Edge(c);
        Edge edged = new Edge(d);
        Edge edgee = new Edge(e);
        Edge edgef = new Edge(f);
        Edge edgeg = new Edge(g);

        List<Edge> list = new ArrayList<>();
        list.add(edgeb);
        list.add(edgec);
        list.add(edged);
        a.setEdges(list);

        List<Edge> list2 = new ArrayList<>();
        list2.add(edgee);
        b.setEdges(list2);

        List<Edge> list3 = new ArrayList<>();
        list3.add(edgeg);
        c.setEdges(list3);

        List<Edge> list4 = new ArrayList<>();
        list4.add(edgef);
        d.setEdges(list4);

        List<Edge> list5 = new ArrayList<>();
        list5.add(edgeg);
        f.setEdges(list5);

        List<Edge> list6 = new ArrayList<>();
        list6.add(edgeg);
        e.setEdges(list6);
        return graph;
    }

    public static void main(String[] args) {
        List<Vertex> graph = initData();
        List<Vertex> topoSortRes = topoSort(graph);
        List<String> strList = new ArrayList<>();
        for (Vertex vertex : topoSortRes) {
            strList.add(vertex.getName());
        }
        System.out.println(strList);
        System.out.println(isLooop(graph));
    }

5.Dijkstra


    public static void main(String[] args) {
        dijkstra();
        dijkstraPriorityQueue();
    }

    public static List<Vertex> init() {
        Vertex v1 = new Vertex("v1");
        Vertex v2 = new Vertex("v2");
        Vertex v3 = new Vertex("v3");
        Vertex v4 = new Vertex("v4");
        Vertex v5 = new Vertex("v5");
        Vertex v6 = new Vertex("v6");
        v1.setDist(0);

        Edge edge13 = new Edge(v3, 9);
        Edge edge12 = new Edge(v2, 7);
        Edge edge16 = new Edge(v2, 14);
        List<Edge> edges1 = new ArrayList<>();
        edges1.add(edge13);
        edges1.add(edge12);
        edges1.add(edge16);
        v1.setEdges(edges1);

        Edge edge14 = new Edge(v4, 20);
        List<Edge> edges2 = new ArrayList<>();
        edges2.add(edge14);
        v2.setEdges(edges2);

        Edge edge36 = new Edge(v6, 2);
        Edge edge34 = new Edge(v4, 11);
        List<Edge> edges3 = new ArrayList<>();
        edges3.add(edge36);
        edges3.add(edge34);
        v3.setEdges(edges3);

        Edge edge45 = new Edge(v5, 6);
        List<Edge> edges4 = new ArrayList<>();
        edges4.add(edge45);
        v4.setEdges(edges4);

        Edge edge65 = new Edge(v5, 9);
        List<Edge> edges6 = new ArrayList<>();
        edges6.add(edge65);
        v6.setEdges(edges6);

        List<Vertex> list = new ArrayList<>();
        list.add(v1);
        list.add(v2);
        list.add(v3);
        list.add(v4);
        list.add(v5);
        list.add(v6);
        return list;
    }

    public static void dijkstra() {
        List<Vertex> graph = init();
        List<Vertex> graph2 = new ArrayList<>(graph);
        getDist(graph2);
        for (Vertex vertex : graph) {
            System.out.println(vertex.getName() + " " + vertex.getDist());
        }
    }
    public static void dijkstraPriorityQueue() {
        List<Vertex> graph = init();
        PriorityQueue<Vertex> dijkstraPriorityQueue =
                new PriorityQueue<>((v1, v2) -> v1.getDist() - v2.getDist());
        for (Vertex vertex : graph) {
            dijkstraPriorityQueue.add(vertex);
        }
        while (!dijkstraPriorityQueue.isEmpty()) {
            Vertex minDiskVertex = dijkstraPriorityQueue.peek();
            updateWeighBoursDist(minDiskVertex, dijkstraPriorityQueue);
            dijkstraPriorityQueue.poll();
        }
        for (Vertex vertex : graph) {
            System.out.println(vertex.getName() + " " + vertex.getDist());
        }
    }

    public static void getDist(List<Vertex> notCompleteVisitedList) {
        while (!notCompleteVisitedList.isEmpty()) {
            Vertex minDistVertex = findMinDistVertex(notCompleteVisitedList);
            updateWeighBoursDist(minDistVertex, notCompleteVisitedList);
            notCompleteVisitedList.remove(minDistVertex);
        }
    }

    /**
     * 更新相邻顶点的距离
     * @param cur  从当前顶点出发
     * @param list  所有没有访问完成的顶点集合
     */
    public static void updateWeighBoursDist(Vertex cur, List<Vertex> list) {
        if (CollectionUtil.isNotEmpty(cur.getEdges())) {
            for (Edge edge : cur.getEdges()) {
                Vertex n = edge.getLinked();
                if (list.contains(n)) {
                    int dist = cur.getDist() + edge.getWeight();
                    if (dist < n.getDist()) {
                        n.setDist(dist);
                    }
                }
            }
        }
    }

    public static Vertex findMinDistVertex(List<Vertex> graph) {
        if (CollectionUtil.isNotEmpty(graph)) {
            Vertex min = graph.get(0);
            for (int i = 1; i < graph.size(); i++) {
                if (min.getDist() > graph.get(i).getDist()) {
                    min = graph.get(i);
                }
            }
            return min;
        }
        return null;
    }

6.Test

public static void main(String[] args) {
        Vertex vertex = initData();
        List<String> res = new ArrayList<>();
        dfs(vertex, res);
        System.out.println(JSON.toJSONString(res));

        List<String> res1 = new ArrayList<>();
        vertex = initData();
        dfsStack(vertex, res1);
        System.out.println(JSON.toJSONString(res1));
        
        List<String> res2 = new ArrayList<>();
        vertex = initData();
        bfsQueue(vertex, res2);
        System.out.println(JSON.toJSONString(res2));

        /**
         * 基础: LinkedList用于stack
         */
        List<String> stackRes = new ArrayList<>();
        LinkedList<String> list = new LinkedList();
        list.push("1");
        list.push("2");
        list.push("3");
        list.push("4");
        list.push("5");
        for (int i = 0; i < 5; i++) {
            stackRes.add(list.pop());
        }
        System.out.println(JSON.toJSONString(stackRes));

        /**
         * 基础: LinkedList用于queue
         */
        List<String> queueRes = new ArrayList<>();
        LinkedList<String> queue = new LinkedList();
        queue.push("1");
        queue.push("2");
        queue.push("3");
        queue.push("4");
        queue.push("5");
        for (int i = 0; i < 5; i++) {
            queueRes.add(queue.pollLast());
        }
        System.out.println(JSON.toJSONString(queueRes));
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值