拓扑排序-简单实现

package com.ygy.test.sort;

import lombok.Getter;
import lombok.Setter;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * Created by guoyao on 2017/10/11.
 */

//简单的拓扑排序
public class TopologicalSorting {

    //定义顶点信息
    private static class Vertex {

        @Getter @Setter
        private  int indegree;  //入度

        @Getter @Setter
        private String name ;  //顶点信息

        public Vertex(String name) {
            this.name=name;
            indegree = 0 ;   //初始入度为0
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            Vertex vertex=(Vertex) o;

            return name.equals(vertex.name);
        }

        @Override
        public int hashCode() {
            return name.hashCode();
        }
    }

    //定义拓扑关系图
    private static class TopoGraph {

        public Map<Vertex, Set<Vertex>> relMap=new HashMap<>();  //顶点与节点关系

        public Set<Vertex> vertices=new HashSet<>();  //所有节点信息

        //添加顶点关系图
        public boolean addRelVertex(Vertex start, Vertex end) {

            //根据name判断重复
            vertices.add(start);
            vertices.add(end);

            Set<Vertex> adjcents=relMap.get(start);  //相邻节点信息
            if (CollectionUtils.isEmpty(adjcents)) {
                adjcents = new HashSet<>();
            }

            if (adjcents.contains(end)) {
                return false;
            }

            adjcents.add(end);
            int indegree=end.getIndegree();
            end.setIndegree(++indegree);    //入度+1
            relMap.put(start, adjcents);
            return true;
        }
    }

    public static List<Vertex> topo_sort(TopoGraph topoGraph) throws Exception {
        Queue<Vertex> zeroIndegree=new LinkedList<>();
        List<Vertex> resultList=new ArrayList<>();
        int count = topoGraph.vertices.size() ;  //用来统计节点数,判断是否闭环
        //将所有入度为0的节点入队列
        for (Vertex vertex : topoGraph.vertices) {
            int indegree=vertex.getIndegree();
            if (indegree == 0) {
                zeroIndegree.add(vertex);
            }
        }

        //遍历队列
        while (!zeroIndegree.isEmpty()) {
            Vertex vertex=zeroIndegree.poll();

            resultList.add(vertex);  //入结果队列

            Set<Vertex> adjacents=topoGraph.relMap.get(vertex);  //相邻节点信息

            if (!CollectionUtils.isEmpty(adjacents)) {
                for (Vertex adj : adjacents) {
                    int indegree=adj.getIndegree();
                    adj.setIndegree(--indegree);
                    if (0 == indegree) {    //如果入度将为0 ,则依赖节点已都出队列
                        zeroIndegree.add(adj);
                    }
                }
            }
        }

        if (count != resultList.size()) {
            throw new RuntimeException(" 闭环");
        }
        return resultList;

    }


    public static void main(String[] args) throws Exception  {

        Vertex vertexA=new Vertex("A");
        Vertex vertexB=new Vertex("B");
        Vertex vertexC=new Vertex("C");
        Vertex vertexD=new Vertex("D");
        Vertex vertexE=new Vertex("E");
        TopoGraph topoGraph=new TopoGraph();
        topoGraph.addRelVertex(vertexA, vertexB);
        //topoGraph.addRelVertex(vertexA, vertexC);
        topoGraph.addRelVertex(vertexC, vertexD);
        topoGraph.addRelVertex(vertexB, vertexD);
        topoGraph.addRelVertex(vertexD, vertexE);
        List<Vertex> result=null;
        //try {
            result = topo_sort(topoGraph);
        //} catch (Exception e) {
        //    System.out.println(e);
        //}

        if (result != null) {
            for (Vertex vertex : result) {
                System.out.println(vertex.getName());
            }
        }

    }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值