拓扑序练习(一)

题目
LintCode127
给定一个有向图,图节点的拓扑排序定义如下:

对于图中的每一条有向边 A -> B , 在拓扑排序中A一定在B之前.
拓扑排序中的第一个节点可以是图中的任何一个没有其他节点指向它的节点。

如下图所示:
在这里插入图片描述
拓扑排序可以为:
[0, 1, 2, 3, 4, 5]
[0, 2, 3, 1, 5, 4]

其中给定的数据结构是:表示的意思是DirectedGraphNode是一个点的描述类。label是点的value,neighbors是这个点所有的邻居。没有边的任何信息以及权重。
主方法就是topSort,根据给定的这个graph,实现它的拓扑排序。

 class DirectedGraphNode {
        int label;
        List<DirectedGraphNode> neighbors;

        DirectedGraphNode(int x) {
            label = x;
            neighbors = new ArrayList<DirectedGraphNode>();
        }
    }
	 public ArrayList<DirectedGraphNode> topSort(ArrayList<DirectedGraphNode> graph) {
        
    }

分析

  1. 如果从A点出发经过所有的节点都算上为100。从B点出发经过所有的点都算上为80。那么就可以认为A的拓扑序在B的前面。两种情况。
    1.1 AB点之间存在依赖关系,那么肯定是B依赖A点,不然不可能A所有的节点数>B所有节点数。
    1.2 如果AB之间不存在依赖关系,那么AB谁在前无所谓,对于拓扑序来说,AB是在前都可以。所以可以规定如果A节点数>=B节点数。A的拓扑序在前。
  2. 如果节点数量特别多,如果想要得到0节点后面一共有多少节点数(以上图为例),那么它要遍历1,2,3,4,5后面所有的节点,想要得到1节点后面节点数也一样要遍历后面的所有。所以,为了更方便的获取到每个节点的后续所有节点数,用Map来作为缓存,算出来放到Map中。随用随取。

代码

//LintCode提供类,不要提交这个类
    class DirectedGraphNode {
        int label;
        List<DirectedGraphNode> neighbors;

        DirectedGraphNode(int x) {
            label = x;
            neighbors = new ArrayList<DirectedGraphNode>();
        }
    }

    public ArrayList<DirectedGraphNode> topSort(ArrayList<DirectedGraphNode> graph) {
        HashMap<DirectedGraphNode, Record> order = new HashMap<>();
        //上来先计算出每个节点包含的子节点个数
        for (DirectedGraphNode node : graph) {
            f(node, order);
        }

        ArrayList<Record> records = new ArrayList<>();
        for (Record record : order.values()) {
            records.add(record);
        }
        //根据自己实现的比较器,进行排序(节点数量多的在前)
        records.sort(new MyComparator());
		//排序后,放到list,return
        ArrayList<DirectedGraphNode> ans = new ArrayList<>();
        for (Record record : records) {
            ans.add(record.node);
        }
        return ans;
    }

    public static class Record {
        public DirectedGraphNode node;
        public long nodes;

        public Record(long nodes, DirectedGraphNode node) {
            this.nodes = nodes;
            this.node = node;
        }
    }
	//自定义比较器
    public static class MyComparator implements Comparator<Record> {

        @Override
        public int compare(Record o1, Record o2) {
            return o1.nodes == o2.nodes ? 0 : (o1.nodes > o2.nodes ? -1 : 1);
        }
    }
	
	//f()函数用来计算每个节点后续包含多少节点
	//cur:当前节点
	//order:缓存Map,包含着每个节点后续挂了多少节点
    public static Record f(DirectedGraphNode cur, HashMap<DirectedGraphNode, Record> order) {
    	//如果map中包含当前节点,说明已经算过了,直接return
        if (order.containsKey(cur)) {
            return order.get(cur);
        }

        long nodes = 0;
        //拿到当前节点所有邻居
        for (DirectedGraphNode next : cur.neighbors) {
        	//递归调用f()函数,累加
            nodes += f(next, order).nodes;
        }
		//封装成Record,节点个数加上自己
        Record record = new Record(nodes + 1, cur);
        //放入map中随用随取
        order.put(cur, record);
        return record;
    }

上面的方法是通过点次、点数的方法来实现拓扑排序,还可以根据XY节点的深度来进行判断,同理,如果X节点的深度 >= Y节点,就可以认为X节点的拓扑序在Y节点之前。

代码实现
在f()函数中,利用递归获取每个节点的深度。

 public ArrayList<DirectedGraphNode> topSort(ArrayList<DirectedGraphNode> graph) {
        HashMap<DirectedGraphNode, Record> order = new HashMap<>();

        for (DirectedGraphNode cur : graph) {
            f(cur, order);
        }
        List<Record> sortArr = new ArrayList<>();
        for (Record record : order.values()) {
            sortArr.add(record);
        }

        sortArr.sort(new MyComparator());

        ArrayList<DirectedGraphNode> ans = new ArrayList<>();
        for (Record record : sortArr) {
            ans.add(record.node);
        }
        return ans;
    }

    public static class Record {
        int deep;
        DirectedGraphNode node;

        public Record(int d, DirectedGraphNode n) {
            this.deep = d;
            this.node = n;
        }
    }

    public static class MyComparator implements Comparator<Record> {

        @Override
        public int compare(Record o1, Record o2) {
            return o2.deep - o1.deep;
        }
    }

    public static Record f(DirectedGraphNode cur, HashMap<DirectedGraphNode, Record> order) {
        if (order.containsKey(cur)) {
            return order.get(cur);
        }

        int follow = 0;
        for (DirectedGraphNode next : cur.neighbors) {
            follow = Math.max(follow, f(next, order).deep);
        }

        Record record = new Record(follow + 1, cur);
        order.put(cur,record);
        return record;
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值