Java数据结构-图

最近在学《算法 第四版》,刚学完无向图的深度优先搜索和广度优先搜索,并参照示例,写了支持泛型的Graph类,并同样写了支持泛型的搜索类,仅供参考。

package org.tafia.graph;

import java.util.Set;

/**
 * 顶点为类型T的图
 * 
 * @author Dason
 * @date 2016年10月12日
 *
 */
public interface Graph<T> {

    /**
     * 所有顶点
     * @return 顶点的集合
     */
    Set<T> vertex();
    /**
     * 边的数量
     * @return 边的数量
     */
    int edge();
    /**
     * 连接顶点v1和v2
     * @param v1 顶点1
     * @param v2 顶点2
     */
    void join(T v1, T v2);
    /**
     * 与顶点v相连的顶点
     * @param vertex
     * @return 顶点的集合
     */
    Set<T> adjoin(T v);

}
package org.tafia.graph;

import java.util.Set;

public class AbstractGraph<T> implements Graph<T> {

    @Override
    public Set<T> vertex() {
        throw new UnsupportedOperationException();
    }

    @Override
    public int edge() {
        throw new UnsupportedOperationException();
    }

    @Override
    public void join(T v1, T v2) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Set<T> adjoin(T v) {
        throw new UnsupportedOperationException();
    }

}
package org.tafia.graph;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class HashUndirectedGraph<T> extends AbstractGraph<T> {

    private Map<T, Set<T>> adjoinMap;
    private int numOfEdges = 0;

    /**
     * 创建指定顶点的无向图
     * @param vertexList 顶点集合
     */
    public HashUndirectedGraph(Set<T> vertexList) {
        adjoinMap = new HashMap<>(vertexList.size());
        for (T v : vertexList) {
            adjoinMap.put(v, new HashSet<>());
        }
    }

    @Override
    public Set<T> vertex() {
        Set<T> set = new HashSet<>();
        for (T v : adjoinMap.keySet()) {
            set.addAll(adjoinMap.get(v));
        }
        return set;
    }

    @Override
    public int edge() {
        return numOfEdges;
    }

    @Override
    public void join(T v1, T v2) {
        if (!adjoinMap.containsKey(v1) || !adjoinMap.containsKey(v2)){
            return;
        }
        adjoinMap.get(v1).add(v2);
        adjoinMap.get(v2).add(v1);
        numOfEdges++;
    }

    @Override
    public Set<T> adjoin(T v) {
        return adjoinMap.get(v);
    }
}
package org.tafia.graph;

import java.util.List;

public interface GraphSearch<T> {

    /**
     * 是否包含到顶点v的路径
     * @param v 顶点
     * @return 如果包含返回true,否则返回false
     */
    boolean hasPathTo(T v);
    /**
     * 返回到顶点v的路径集合
     * @param v 顶点
     * @return 路径集合
     */
    List<T> pathTo(T v);
}
package org.tafia.graph;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;

public class DeepFirstGraphSearch<T> implements GraphSearch<T> {

    private Map<T, Boolean> marked = new HashMap<>();
    private Map<T, T> pathTo = new HashMap<>();
    private T vertex;
    /**
     * 构造器
     * @param graph 图
     * @param vertex 操作的顶点
     */
    public DeepFirstGraphSearch(Graph<T> graph, T vertex) {
        this.vertex = vertex;
        for (T v : graph.vertex()) {
            marked.put(v, Boolean.FALSE);
        }
        dfs(graph, vertex);
    }

    private void dfs(Graph<T> graph, T vertex) {
        marked.put(vertex, Boolean.TRUE);
        for (T v : graph.adjoin(vertex)) {
            if (!marked.get(v)) {
                pathTo.put(v, vertex);
                dfs(graph, v);
            }
        }
    }

    @Override
    public boolean hasPathTo(T v) {
        return marked.get(v);
    }

    @Override
    public List<T> pathTo(T v) {
        Stack<T> stack = new Stack<>();
        for (; v != vertex; v = pathTo.get(v)) {
            stack.push(v);
        }
        List<T> list = new ArrayList<>(stack.size() + 1);
        list.add(vertex);
        while (!stack.isEmpty()) {
            list.add(stack.pop());
        }
        return list;
    }

    public static void main(String[] args) {
        Set<String> cities = new HashSet<>();
        cities.add("北京");
        cities.add("天津");
        cities.add("河南");
        cities.add("河北");
        cities.add("山东");
        cities.add("山西");
        Graph<String> graph = new HashUndirectedGraph<>(cities);
        graph.join("北京", "天津");
        graph.join("北京", "河北");
        graph.join("河北", "山西");
        graph.join("河北", "天津");
        graph.join("山西", "山东");
        graph.join("天津", "山东");
        graph.join("天津", "河南");
        String from = "山西";
        GraphSearch<String> gs = new DeepFirstGraphSearch<>(graph, from);
        for (String to : graph.vertex()) {
            boolean hasPathTo = gs.hasPathTo(to);
            System.out.println(hasPathTo ? gs.pathTo(to) : from+"×"+to);
        }
    }

}
package org.tafia.graph;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.Stack;
import java.util.concurrent.LinkedBlockingQueue;

public class BreadthFirstGraphSearch<T> implements GraphSearch<T> {

    private Map<T, Boolean> marked = new HashMap<>();
    private Map<T, T> pathTo = new HashMap<>();
    private T vertex;
    /**
     * 构造器
     * @param graph 图
     * @param vertex 操作的顶点
     */
    public BreadthFirstGraphSearch(Graph<T> graph, T vertex) {
        this.vertex = vertex;
        for (T v : graph.vertex()) {
            marked.put(v, Boolean.FALSE);
        }
        bfs(graph, vertex);
    }

    private void bfs(Graph<T> graph, T vertex) {
        marked.put(vertex, Boolean.TRUE);
        Queue<T> queue = new LinkedBlockingQueue<>();
        queue.offer(vertex);
        while (!queue.isEmpty()) {
            vertex = queue.poll();
            for (T v : graph.adjoin(vertex)) {
                if (!marked.get(v)) {
                    marked.put(v, Boolean.TRUE);
                    pathTo.put(v, vertex);
                    queue.offer(v);
                }
            }
        }
    }

    @Override
    public boolean hasPathTo(T v) {
        return marked.get(v);
    }

    @Override
    public List<T> pathTo(T v) {
        Stack<T> stack = new Stack<>();
        for (; v != vertex; v = pathTo.get(v)) {
            stack.push(v);
        }
        List<T> list = new ArrayList<>(stack.size() + 1);
        list.add(vertex);
        while (!stack.isEmpty()) {
            list.add(stack.pop());
        }
        return list;
    }

    public static void main(String[] args) {
        Set<String> cities = new HashSet<>();
        cities.add("北京");
        cities.add("天津");
        cities.add("河南");
        cities.add("河北");
        cities.add("山东");
        cities.add("山西");
        Graph<String> graph = new HashUndirectedGraph<>(cities);
        graph.join("北京", "天津");
        graph.join("北京", "河北");
        graph.join("河北", "山西");
        graph.join("河北", "天津");
        graph.join("山西", "山东");
        graph.join("天津", "山东");
        graph.join("天津", "河南");
        String from = "北京";
        GraphSearch<String> gs = new BreadthFirstGraphSearch<>(graph, from);
        for (String to : graph.vertex()) {
            boolean hasPathTo = gs.hasPathTo(to);
            System.out.println(hasPathTo ? gs.pathTo(to) : from+"×"+to);
        }
    }

}

上述代码在这里下载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值