Ruby Heapsort:`sink';:未定义的方法`>';零级:零级
我目前正在写这本书。我试图实现堆排序,但遇到了一个错误 “sink”:nil:NilClass的未定义方法>” 发生此错误的原因是,当数组被传递到Ruby Heapsort:`sink';:未定义的方法`>';零级:零级,ruby,algorithm,heapsort,Ruby,Algorithm,Heapsort,我目前正在写这本书。我试图实现堆排序,但遇到了一个错误 “sink”:nil:NilClass的未定义方法>” 发生此错误的原因是,当数组被传递到sort方法时,它在0索引处有11个元素。当它用1交换索引n(数组中的元素数)时,将nil与字符串进行比较。意思是n是11,但是没有11索引,因为数组索引从0开始 以下是本书中堆排序方法的Java实现: public static void sort(Comparable[] a) { int N = a.length; fo
sort
方法时,它在0索引处有11个元素。当它用1交换索引n
(数组中的元素数)时,将nil
与字符串进行比较。意思是n
是11,但是没有11索引,因为数组索引从0开始
以下是本书中堆排序方法的Java实现:
public static void sort(Comparable[] a)
{
int N = a.length;
for (int k = N/2; k >= 1; k--)
sink(a, k, N);
while (N > 1)
{
exch(a, 1, N--);
sink(a, 1, N);
}
}
下面是Ruby中的实现:
def sort(a)
n = a.length
k = n/2
while k >= 1
sink(a, k, n)
k -= 1
end
while n > 1
swap(a, 1, n)
n -= 1
sink(a, 1, n)
end
a
end
现在,在这本书中,数组忽略了位置a[0]
并从a[1]
开始,但我有点不清楚Java实现中的sort
方法是如何实现的。我也有点奇怪,该方法需要传递一个从索引1
开始的数组。因此我的理解是Java实现中的sort
方法将设置数组
请注意,在示例中,数组中的第一个元素是如何从索引1a[1]
开始的。这是在排序方法中完成的吗?意思是重新排列数组以从索引1开始
Ruby中sort
的Ruby实现是否正确?还是有错误
堆排序的完整实现
class Heap
# Trickledown
def sink(a, k, n)
while 2 * k <= n
j = 2 * k # child
if !a[j + 1].nil? # check if there is a right child
j += 1 if j > 1 && less(a, j, j + 1) # if left child less than right child
end
break if !less(a, k, j) # If parent greater than child break
swap(a, k, j)
k = j
end
end
def sort(a)
n = a.length
k = n / 2
while k >= 1
sink(a, k, n)
k -= 1
end
while n > 1
swap(a, 1, n)
n -= 1
sink(a, 1, n)
end
a
end
def less(pq, i, j)
pq[i - 1] < pq[j - 1]
end
def swap(a, i, j)
temp = a[i - 1]
a[i - 1] = a[j - 1]
a[j - 1] = temp
end
end
input = ["S", "O", "R", "T", "E", "X", "A", "M", "P", "L", "E"]
heap = Heap.new
p heap.sort(input)
但正确的答案是
["A", "E", "E", "L", "M", "O", "P", "R", "S", "T", "X"]
错误来自以下行:
if !a[j + 1].nil? # check if there is a right child
此行检查是否存在右节点。堆排序实现中的问题是,我们在每次迭代中将n
减少一个
while n > 1
swap(a, 1, n)
n -= 1
sink(a, 1, n)
end
因此,我们没有跟踪数组中存储在索引n
上的元素。虽然数组中存储有值,但我们仅将a[0]
到a[n]
视为堆。
因此,我不应该检查a[j+1]
是否为零,而应该检查j+1
是否小于或等于n
def sink(a, k, n)
while 2 * k <= n
j = 2 * k # child
if j + 1 <= n # check if there is a right child
j += 1 if j > 1 && less(a, j, j + 1) # if left child less than right child
end
break if !less(a, k, j) # If parent greater than child break
swap(a, k, j)
k = j
end
end
def接收器(a、k、n)
而2*k错误消息指向sink
方法。如果a[k]>a[j]
,则可以调用
的唯一行是中断。我猜在一些swap
call(s)之后,初始数组被nil
s损坏,因为[a.size]是nil
,并且您的n
可以达到s.size
正确,这就是我在帖子中描述的。但是在Java实现中是如何做到这一点的呢?请注意数组是如何从索引1开始的。您将获得数据的中间快照。跟踪执行情况并验证快照是否相同。
def sink(a, k, n)
while 2 * k <= n
j = 2 * k # child
if j + 1 <= n # check if there is a right child
j += 1 if j > 1 && less(a, j, j + 1) # if left child less than right child
end
break if !less(a, k, j) # If parent greater than child break
swap(a, k, j)
k = j
end
end