Bellman-Ford Code

package _Algorithm.BellmanFord

class BellmanFord {
    //create graph
    val ab = Edge("A", "B", -1)
    val ac = Edge("A", "C", 4)
    val bc = Edge("B", "C", 3)
    val be = Edge("B", "E", 2)
    val ed = Edge("E", "D", -3)
    val dc = Edge("D", "C", 5)
    val bd = Edge("B", "D", 2)
    val db = Edge("D", "B", 1)

    val edges = arrayOf(ab, ac, bc, be, bd, ed, dc, db)

    //store cost of each node
    val costMap = HashMap<String, Int>()
    //store parent of each node
    val parentMap = HashMap<String, String>()

    init {
        //init node
        costMap.put("A", 0)
        costMap.put("B", Int.MAX_VALUE)
        costMap.put("C", Int.MAX_VALUE)
        costMap.put("D", Int.MAX_VALUE)
        costMap.put("E", Int.MAX_VALUE)
    }

    fun handler() {
        //relax for every edge
        for (i in 1 until costMap.size) {
            var hasChange = false
            for (edge in edges) {
                val startPointCost = if (costMap.get(edge.startPoint) == null) 0 else costMap.get(edge.startPoint) ?: 0
                val endPointCost = if (costMap.get(edge.endPoint) == null) 0 else costMap.get(edge.endPoint) ?: 0
                //if cur edge's endPointCost large than (startPointCost + edge.weight),
                //that's mean there is shorter path exist
                if (endPointCost > (startPointCost + edge.weight)) {
                    costMap.put(edge.endPoint, startPointCost + edge.weight)
                    parentMap.put(edge.endPoint, edge.startPoint)
                    hasChange = true
                }
            }
            //经常还没达到最大遍历次数便已经求出解了,此时可以优化为提前退出循环
            if (!hasChange) {
                break
            }
        }

        //check if exist ring
        var hasRing = false
        for (edge in edges) {
            val startPointCost = if (costMap.get(edge.startPoint) == null) 0 else costMap.get(edge.startPoint) ?: 0
            val endPointCost = if (costMap.get(edge.endPoint) == null) 0 else costMap.get(edge.endPoint) ?: 0
            if (endPointCost > (startPointCost + edge.weight)) {
                hasRing = true
                break
            }
        }

        //print all
        if (!hasRing) {
            for (item in costMap) {
                print("reach target node:${item.key}, minimum cost is: ${item.value}")
                if (parentMap.contains(item.key)) {
                    val pathList = ArrayList<String>()
                    var parentKey = parentMap.get(item.key)
                    while (parentKey != null) {
                        pathList.add(0, parentKey)
                        parentKey = parentMap.get(parentKey)
                    }
                    pathList.add(item.key)
                    print(", path list:")
                    print(pathList.toString().replace(",","->").replace(" ",""))
                }
                println()
            }
        }
    }
}

/**
 * startPoint,起始点
 * endPoint,终点
 * weight,权重
 * */
data class Edge(var startPoint: String, var endPoint: String, var weight: Int)

 

posted @ 2020-06-16 11:21  johnny_zhao  阅读(177)  评论(0编辑  收藏  举报