Lua mergesort bug

时间:2013-05-14 00:55:44

标签: lua mergesort

我正在尝试通过编写基本的mergesort来学习Lua,但由于我也不熟悉mergesorts,我遇到了一些问题。

代码:

arr = {}
status = 0


function return_first_half (list)
    size = #list
    size = size / 2
    t = {}
    for var = 1, size, 2 do
        t[var] = list[var]
    end
    return t
end

function return_last_half (list)
    size = #list
    i = size / 2
    t = {}
    for var = size, i, -1 do
        t[var] = list[var]
    end
    return t
end


function msort (list)
    size = #list
    first_half = {}
    last_half  = {}
    if (size <= 1) then
        return list
    end
    first_half = msort(return_first_half(list))
    last_half = msort(return_last_half(list))
    if (#first_half == 1) then
        if (#last_half == 1) then
            if (first_half[1] > last_half[1]) then
                arr[status] = first_half[1]
                status = status + 1
                arr[status] = last_half[1]
                status = status + 1
            end
            if (first_half[1] < last_half[1])then
                arr[status] = last_half[1]
                status = status + 1
                arr[status] = first_half[1]
                status = status + 1
            end
        end
    end
end

function main ()
    list = {}
    for i = 1, 8, 1 do
        list[i] = io.read()
    end
    msort(list)
    for i = 1, #arr, 1 do
        print (arr[i])
    end
end

main()

当我将输入8降为1时,它会打印nil并退出。有帮助吗?

编辑:修复了数组长度和地址的问题,它现在返回一行的堆栈溢出:

first_half = msort(return_first_half(list))

1 个答案:

答案 0 :(得分:2)

问题是由于计算/复制第一个和第二个半部分时出错,你永远不会退出递归。

但在我开始之前,让我指出你应该总是使用局部变量来临时存储函数。它更快,并且不会使全局表格混乱。实际上你应该总是使用本地(请,请习惯id),除非你真的觉得你需要设置一个全局变量。

现在回到主题: 在return_first_half中,您复制每一项。这是为什么?如果要允许不均匀的表大小,也应该使用math.floor(size / 2)。

return_second_half中相似。我会改为:

function return_last_half (list)
    size = #list
    i = math.floor(size / 2) + 1
    t = {}
    local itemno = 1
    for var = i, size do
        t[itemno] = list[var]
    end
    return t
end

您的版本中的问题:

  • 当表格大小不均匀时,您会得到小数?
  • 您在返回表中的相同位置设置项目,即5,6,7,8。这意味着大小#运算符返回8,尽管项目数为4.实际上,只要数组中存在间隙,就不会定义size运算符的行为。

一般来说,你的算法设计得不是很好,所以我不会再深入了解。我告诉过你如何避免堆栈溢出,所以如果你愿意,可以从那里拿走它。

但是,让我快速实现mergesort,它会对项目进行排序(将它们放回到同一个表中):

local function merge(list, start, middle, stop)
    local temp = {}
    local itemno = 1
    local item1, item2 = start, middle + 1

    while item1 <= middle and item2 <= stop do
        if list[item2] < list[item1] then
            temp[itemno] = list[item2]
            item2 = item2 + 1
        else
            temp[itemno] = list[item1]
            item1 = item1 + 1
        end
        itemno = itemno + 1
    end

    if item1 <= middle then
        while item1 <= middle do
            temp[itemno] = list[item1]
            itemno = itemno + 1
            item1 = item1 + 1
        end
    else
        while item2 <= stop do
            temp[itemno] = list[item2]
            itemno = itemno + 1
            item2 = item2 + 1
        end
    end

    itemno = 1
    for i = start, stop do
        list[i] = temp[itemno]
        itemno = itemno + 1
    end
end

local function msort(list, start, stop)
    if stop - start == 0 then
        return list
    elseif start > stop then
        error("Oh crap")
    end

    local middle = math.floor((stop + start) / 2)
    msort(list, start, middle)
    msort(list, middle + 1, stop)
    merge(list, start, middle, stop)
end

local function main ()
    list = {}
    print("Enter number of items:")
    local i = tonumber(io.read())
    for item = 1, i do
        print("Enter item number " .. item .. ":")
        list[item] = tonumber(io.read())
    end
    msort(list, 1, i)
    for k, v in ipairs(list) do
        print (v)
    end
end

main()

编辑:

关于这个简单的递归实现需要注意的一件事是,如果列表足够大,你最终会遇到堆栈溢出。