贪婪算法应用示例1(dijkstra算法-lua实现)

 

示例应用:找出图上面的a到b的最短距离,即点1到点5的最短距离

-- 算法思路
-- 1:获取要检测的节点,如果是第一个时,则为第一个节点,否则从待检测的节点列表当中选取(选取之后则进行移除)
-- 2:获取此节点与下一个节点所有可能的字段(下一个节点不包含已经检测过的点),并把点依次添加到待检测的节点列表(待检测的节点不能包含结束节点)
-- 3:合并所有字段到每一条含有该节点的路径里(尾节点含有该节点的每一条路径)
-- 4:进行筛选(对合并后的字段,对头尾相同的路径进行最优选择)
-- 5:如果检测到最终的节点后,记录当前已经检测的完整路径的最优解(最优路径和最优值),
    -- 对当前所有的路径的总值和最优值进行比较进行筛选;若没有检测最终的节点,则重复第一步,直到没有要检测的节点为止


local function copy(list)
    local newList = {}
    for k,v in pairs(list) do
        newList[k] = v
    end
    return newList
end


local function isContain(list, value)
    local isContain = false
    for k,v in pairs(list) do
        if v == value then
            isContain = true
        end
    end
    return isContain
end


local Greedy = {}


function Greedy:new(lineList, startIndex, endIndex)
    self.lineList   = lineList
    self.startIndex = startIndex
    self.endIndex   = endIndex


    self:init()
    return self
end


function Greedy:init()
    self.curAllPathList = {}
    self.waitCheckList  = {}
    self.checkList      = {}
    self.minValue       = nil -- 最优解
    self.minPathList    = nil -- 最优的路径(不一定只有一条)
end


function Greedy:getValue(index1, index2)
    for k,v in pairs(self.lineList) do
        local line = v.line
        if (line[1] == index1 and line[2] == index2) or (line[1] == index2 and line[2] == index1) then
            return v.value
        end
    end
    return nil
end


function Greedy:printPathList(pathList)
    for k,v in pairs(pathList) do
        print(string.format("path = %s, value = %d", table.concat(v.path, "-"), v.value))
    end
end


-- 获取最短的路径
function Greedy:getShortPath()
    
    self:init()


    self.waitCheckList = {self.startIndex}


    local index = self:getNextCheckPoint() 
    while true do
        self:updateNewPath(index)
        self.checkList[#self.checkList+1] = index
        index = self:getNextCheckPoint()


        if not index then
            break
        end
    end
    self:printPathList(self.curAllPathList)
end


function Greedy:getPathValue(path)
    local sum = 0
    for i=1, #path-1 do
        sum = sum + self:getValue(path[i], path[i+1])
    end
    return sum
end


function Greedy:getAllCurNextPoint(curPoint)
    local pointList = {}
    for k,v in pairs(self.lineList) do
        local p1 = v.line[1]
        local p2 = v.line[2]


        if p1 == curPoint then
            if not isContain(pointList, p2) then
                pointList[#pointList+1] = p2
            end
        end
        if p2 == curPoint then
            if not isContain(pointList, p1) then
                pointList[#pointList+1] = p1
            end
        end
    end


    for k,v in pairs(self.checkList) do
        for k2,v2 in pairs(pointList) do
            if v == v2 then
                table.remove(pointList, k2)
                break
            end
        end
    end


    return pointList
end


function Greedy:updateNewPath(curPoint)


    if #self.curAllPathList == 0 then
        local list = self:getAllCurNextPoint(curPoint)
        for k,v in pairs(list) do
            local path = {curPoint, v}
            self.curAllPathList[#self.curAllPathList+1] = {path=path, value=self:getPathValue(path)}
        end
        self:addToWaitCheckList(list)
    else
        local newList = {}
        local count = #self.curAllPathList
        for i=1, count do
            for k,v in pairs(self.curAllPathList) do
                if v.path[#v.path] == curPoint then
                    local list = self:getAllCurNextPoint(curPoint)
                    self:addToWaitCheckList(list)
                    for _,v2 in pairs(list) do
                        local oneList = copy(v.path)
                        oneList[#oneList+1] = v2
                        newList[#newList+1] = {path=oneList, value=self:getPathValue(oneList)}
                    end
                    table.remove(self.curAllPathList, k)
                    break
                end
            end
        end


        for k,v in pairs(newList) do
            self:updateCurAllPathList(v)
        end
    end


end


function Greedy:updateCurAllPathList(pathList)


    local function isSameEndPath(pathList1, pathList2)
        return pathList1[1] == pathList2[1] and pathList1[#pathList1] == pathList2[#pathList2]
    end


    local function checkAllPathList()


        for k,v in pairs(self.curAllPathList) do
            if v.path[#v.path] == self.endIndex then
                if not self.minValue then
                    self.minValue = v.value
                    self.minPathList = v
                elseif self.minValue > v.value then
                    minValue = v.value
                    self.minPathList = v
                end
            end
        end


        if self.minValue then
            local count = #self.curAllPathList
            for i=1, count do
                for k,v in pairs(self.curAllPathList) do
                    if v.value > self.minValue then
                        table.remove(self.curAllPathList, k)
                        break
                    end
                end
            end
        end
    end


    for k,v in pairs(self.curAllPathList) do
        local path = v.path
        local path2 = pathList.path
        if path[1] == path2[1] and path[#path] == path2[#path2] then
            if v.value > pathList.value then -- 局部最优替换
                table.remove(self.curAllPathList, k)
                self.curAllPathList[#self.curAllPathList+1] = pathList
                checkAllPathList()
                return
            elseif v.value < pathList.value then
                return 
            end
        end
    end


    self.curAllPathList[#self.curAllPathList+1] = pathList
    checkAllPathList()


end


-- 获取下一个检查点(每获取一次列表里就移除一次)
function Greedy:getNextCheckPoint()
    if #self.waitCheckList == 0 then  
        return nil -- 代表已经没有可检查的点了
    end


    local point = self.waitCheckList[1]
    table.remove(self.waitCheckList, 1)
    return point
end


function Greedy:addToWaitCheckList(list)
    for k,v in pairs(list) do
        if not isContain(self.waitCheckList, v) and not isContain(self.checkList, v) and v ~= self.endIndex then
            self.waitCheckList[#self.waitCheckList+1] = v
        end
    end
end


local lineList = {}
lineList[#lineList+1] = {line={1,2}, value=7}
lineList[#lineList+1] = {line={1,3}, value=9}
lineList[#lineList+1] = {line={1,6}, value=14}


lineList[#lineList+1] = {line={2,1}, value=7}
lineList[#lineList+1] = {line={2,3}, value=10}
lineList[#lineList+1] = {line={2,4}, value=15}


lineList[#lineList+1] = {line={3,1}, value=9}
lineList[#lineList+1] = {line={3,2}, value=10}
lineList[#lineList+1] = {line={3,4}, value=11}
lineList[#lineList+1] = {line={3,6}, value=2}


lineList[#lineList+1] = {line={4,3}, value=11}
lineList[#lineList+1] = {line={4,2}, value=15}
lineList[#lineList+1] = {line={4,5}, value=6}


lineList[#lineList+1] = {line={5,4}, value=6}
lineList[#lineList+1] = {line={5,6}, value=9}


lineList[#lineList+1] = {line={6,1}, value=14}
lineList[#lineList+1] = {line={6,3}, value=2}
lineList[#lineList+1] = {line={6,5}, value=9}


local g = Greedy:new(lineList, 1, 5)
g:getShortPath()
参考链接: https://brilliant.org/wiki/greedy-algorithm/
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值