我正在尝试通过编写基本的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))
答案 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
您的版本中的问题:
#
运算符返回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()
编辑:
关于这个简单的递归实现需要注意的一件事是,如果列表足够大,你最终会遇到堆栈溢出。