美文网首页
代价一致算法 寻找最小路径 最终版本

代价一致算法 寻找最小路径 最终版本

作者: 卖毛玉的小贩 | 来源:发表于2017-12-13 16:52 被阅读0次

    八月份的时候写了一篇代价一致算法的简单版,今天突然想起来,给最终版上传一下。

    直接上代码,里面有写内容用法。  这个代码里  ("1","2",1)这种写法是按照另一个简书作者的来写的。但他的链接已经没了,所以这里上不了,他写的是A*给我带来很大的启发。

    classGraphAdjacencyListNote {

    vardata:AnyObject

    varweightNumber:Int//权值,最小生成树使用

    varpreNoteIndex:Int//最小生成树使用, 记录该节点挂在那个链上

    varnext:GraphAdjacencyListNote?

    varvisited:Bool=false

    init(data:AnyObject=""asAnyObject, weightNumber:Int=0, preNoteIndex:Int=0) {

    self.data= data

    self.weightNumber= weightNumber

    self.preNoteIndex= preNoteIndex

    }

    }

    classGraphAdjacencyList {

    fileprivatevarrelation:Array<(String,String,Int)>

    fileprivatevargraph:Array

    fileprivatevarrelationDic:Dictionary

    init() {

    graph= []

    relationDic= [:]

    relation= []

    }

    /// 创建无向图或者有向图

    ///

    /// - parameter notes:图的所有节点

    /// - parameter relations:图中节点中的关系

    /// - parameter isNotDirection: 边是否有方向

    ///

    /// - returns:

    init(notes:Array, relations:Array<(String,String,Int)>, isNotDirection:Bool) {

    graph= []

    relationDic= [:]

    relation= []

    createGraph(notes: notes, relation: relations, isNotDirection: isNotDirection)

    }

    // MARK: - GraphType

    funccreateGraph(notes:Array, relation:Array<(String,String,Int)>){

    createGraph(notes: notes, relation: relation, isNotDirection:true)

    }

    // MARK: - GraphType

    funccreateGraph(notes:Array, relation:Array<(String,String,Int)>, isNotDirection:Bool){

    self.relation= relation

    foriin0..

    letnote =GraphAdjacencyListNote(data: notes[i]asAnyObject)

    graph.append(note)

    relationDic[notes[i]as!String] = i

    }

    foriteminrelation {

    guardleti =relationDic[item.0],

    letj =relationDic[item.1]else{

    continue

    }

    letweightNumber:Int=Int(item.2asNSNumber)

    letnote2 =GraphAdjacencyListNote(data: jasAnyObject, weightNumber: weightNumber,preNoteIndex: i)

    note2.next=graph[i].next

    graph[i].next= note2

    //无向图

    ifisNotDirection {

    letnote1 =GraphAdjacencyListNote(data: iasAnyObject, weightNumber: weightNumber, preNoteIndex: j)

    note1.next=graph[j].next

    graph[j].next= note1

    }

    }

    }

    funcdisplayGraph() {

    displayGraph(graph:graph)

    }

    funcdisplayGraph(graph:Array) {

    foriin0..

    varcursor:GraphAdjacencyListNote? = graph[i]

    whilecursor !=nil{

    cursor = cursor?.next

    }

    }

    }

    ///MARK: -- 代价一致

    //记录每个结点到起始结点的距离信息

    classDistanceInfo {

    varbef:Int=-1//该结点的直属结点索引

    vardistance:Int=LONG_MAX//起始节点到该结点的距离

    varisInPath =false//标记该节点是否在已生成的路径上

    }

    /// - parameter beginIndex: 最短路径的起始结点

    /// - parameter endIndex:最短路径的结束结点

    funcshortestPathDijkstra(beginIndex:Int, endIndex:Int) ->[AnyObject]{

    ifbeginIndex

    varlist = [NSInteger]()

    // 给数组添加起点

    list.append(beginIndex)

    vardistanceInfos:Array =initDistanceInfo()

    distanceInfos[beginIndex].isInPath=true//标记起始位置

    distanceInfos[beginIndex].distance=0//起始最短路径为0

    while!list.isEmpty{

    list =sorTLiset(list: list,graph: distanceInfos)

    letnod = list.removeFirst()//单独拿出最小节点 最小节点移除

    distanceInfos[nod].isInPath=true

    ifnod == endIndex{returndisplayShortPath(endIndex: endIndex, distanceInfo: distanceInfos)}

    //遍历当前索引在邻接链表中所对应的链上的所有节点

    distanceInfos =countCurrentNoteAllDistance(index: nod, distanceInfos: distanceInfos)

    list.insert(findCurrentMiniDistanceIndex(distanceInfos: distanceInfos),at:0)

    }

    returndisplayShortPath(endIndex: endIndex, distanceInfo: distanceInfos)

    }else{// 非法索引

    return[]

    }

    }

    //将dis中最小的距离的结点移动至队列最前

    funcsorTLiset(list:[NSInteger],graph:[DistanceInfo])->[NSInteger]{

    vararray = list

    varmin = graph.first?.distance

    varidx =0

    for(i,a)inlist.enumerated(){

    ifgraph[a].distance< min!{

    min = graph[a].distance

    idx = i

    }

    }

    lettemp = list[idx]

    array.remove(at: array.index(of:temp)!)

    array.insert(temp,at:0)

    returnarray

    }

    /// 初始化距离信息数组

    ///

    /// - returns: 返回初始化后的信息数组

    privatefuncinitDistanceInfo() ->Array {

    vardistanceInfos:Array = []

    for_in0..

    distanceInfos.append(DistanceInfo())

    }

    returndistanceInfos

    }

    /// 输出最短路径信息

    ///

    /// - parameter endIndex:最短路径结束索引

    /// - parameter distanceInfo: 存储最短路径的数组

    privatefuncdisplayShortPath(endIndex:Int, distanceInfo:Array) ->[AnyObject]{

    varpath:Array = []//存储最短路径的数组

    //串联最小路径

    varindex = endIndex

    whileindex !=-1{

    path.append(index)

    index = distanceInfo[index].bef

    }

    //将最小路径进行进行逆转

    path.reverse()

    varidxArray = [AnyObject]()

    foriin0..

    letindex = path[i]

    idxArray.append(self.graph[index].data)

    varcorsur =self.graph[index].next

    whilecorsur !=nil{

    ifInt(corsur?.dataas!NSNumber) == path[i+1] {

    break

    }

    corsur = corsur?.next

    }

    }

    idxArray.append(self.graph[endIndex].data)

    returnidxArray

    }

    /// 计算链接链表数组中某一个索引对应的节点,到该节点所对应链上的每个结点的距离

    ///

    /// - parameter index:邻接链表上链的索引

    /// - parameter preIndexsAndDistances: 记录起始节点到每个结点的距离的数组

    privatefunccountCurrentNoteAllDistance(index:Int,

    distanceInfos:Array) ->Array {

    vardistanceInfo = distanceInfos

    //遍历当前索引在邻接链表中所对应的链上的所有节点

    varlistCursor =self.graph[index].next

    whilelistCursor !=nil{

    //取出该结点对应的下标

    guardletcurrentNoteIndex:Int= listCursor?.dataas!Int?else{

    returndistanceInfos

    }

    //取出当前索引所对应的距离信息

    letcurrentDistanceInfo = distanceInfo[currentNoteIndex]

    //获取index节点的最短路径

    letindexNoteDistance = distanceInfo[index].distance

    //计算上个结点到当前节点的路径距离

    letdistance:Int= indexNoteDistance + (listCursor?.weightNumber)!

    //如果现在的距离比之前记录的距离要小,则更新前面节点的索引以及距离。

    ifdistance < currentDistanceInfo.distance{

    currentDistanceInfo.bef= index

    currentDistanceInfo.distance= distance

    distanceInfo[currentNoteIndex] = currentDistanceInfo

    }

    listCursor = listCursor?.next

    }

    returndistanceInfo

    }

    /// 查找那些未被探测的点中最小距离的下标并返回

    ///

    /// - parameter preIndexsAndDistance:每个节点距离起始结点最短距离的集合

    ///

    /// - returns:最小距离的下标

    privatefuncfindCurrentMiniDistanceIndex(distanceInfos:Array) ->Int{

    //将当前链中的所有结点计算完路径完毕后,找出未到达且最小的那个节点继续下一轮的循环

    varminDistace =LONG_MAX

    varminIndex =0

    foriin0..

    letitem = distanceInfos[i]

    //该点未探测

    if!item.isInPath{

    ifitem.distance< minDistace {//找出最短的那个路径

    minDistace = item.distance

    minIndex = i

    }

    }

    }

    returnminIndex

    }

    }

    以上是算法代码

    以下是使用代码

    letallGraphNote = ["1","2","3","4","5","6","7","8","9","10","11","12","13",

    "14","15","16","17","18","19","20","21","22","23","24",

    "25","26","27","28","29","30","31","32","33","34","35","36"]

    letrelationDirectedGraphA =

    [("1","2",1),("2","3",1),("3","4",1),("4","10",1),("10","9",1),("10","11",1),

    ("11","12",1),("12","13",1),("13","14",1),("13","8",1),("8","7",1),("7","6",1),

    ("10","15",1),("15","16",1),("16","17",1),("17","18",1),("18","24",1),("24","23",1),

    ("24","25",1),("25","26",1),("26","27",1),("27","28",1),("27","22",1),("22","21",1),

    ("21","20",1),("20","19",1),("19","13",1),("24","29",1),("29","30",1),("30","31",1),

    ("31","32",1),("27","33",1),("34","33",1),("34","35",1),("35","36",1),("5","6",1)]

    用法就是 self.shortestPath(beg:起始点, end:终点) 即可  内容可以根据自己的使用来进行

    func shortestPath(beg:NSInteger,end:NSInteger){

    letgraph = GraphAdjacencyList(notes: allGraphNote,relations: relationDirectedGraphA,isNotDirection:true)

    graph.displayGraph()

    let v = graph.shortestPathDijkstra(beginIndex:beg, endIndex:end)

    if v.count >0{

    objArray.append(v)

    }else{

    print("非法",v)

    }

    }

    相关文章

      网友评论

          本文标题:代价一致算法 寻找最小路径 最终版本

          本文链接:https://www.haomeiwen.com/subject/zxbnixtx.html