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

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

直接上代码,里面有写内容用法。  这个代码里  ("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)

}

}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,734评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,931评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,133评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,532评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,585评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,462评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,262评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,153评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,587评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,792评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,919评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,635评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,237评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,855评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,983评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,048评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,864评论 2 354

推荐阅读更多精彩内容