我必须在Python中构建一个完整的MIN-HEAP实现,而不使用内置的堆函数。
所以我有父,左子和右子的定义,考虑到0中的python数列表元素:
from random import randint
import math
def parent(i):
x = int(l.index(l[i])) #########3
y = int(math.floor(x/2))
return y-1
def lchild(i):
x = int(l.index(l[i]))
y = int(math.floor(x*2))
return y-1
def rchild(i):
x = int(l.index(l[i]))
y = int(math.floor(x*2 + 1))
return y-1
然后我有一部分代码为我生成(伪)随机列表到列表 l :
l = []
dl = int(input)
for i in range (0, dl):
x = int(randint(1,100))
l.append(x)
直到这一刻一切正常。然后我有一个函数bkop,用于将表 l 放入最小堆中。
def bkop(l):
j = 0
for i in range(0, len(l)):
if int(l[i]) < int(parent(l[i])): #########2
l[i], l[parent(i)] = l[parent(i)], l[i]
j = j+1
if j != 0:
bkop(l)
然后我想运行一个程序并查看结果:
bkop(l) #########1
print l
程序崩溃,错误列表索引超出范围指向3行,我用#########标记。我大约一个月前开始写这篇文章,我很确定,那个时候,父母,小孩和小孩都在工作。你知道吗,出了什么问题?
EDIT1: 好的,所以我修复了父/ lchild / rchild定义。我检查过,他们返回正确的值。这是代码:
def parent(i):
x = i + 1
y = x//2
return y-1
def lchild(i):
x = i + 1
y = x*2
return y-1
def rchild(i):
x = i + 1
y = x*2 + 1
return y-1
生成随机列表的函数几乎完好无损。然后我有这个bkop函数(它使 l 列表中的min-heap成为可能)。我故意在使用之前和之后使用印刷品,如果它有效,则使用印刷品......但事实并非如此。它同时返回相同的列表,没有编译错误或任何东西。知道怎么解决吗?
print(l)
def bkop(l):
j = 0
for i in range(0, len(l)):
if l[i] < parent(i):
l[i], l[parent(i)] = l[parent(i)], l[i]
j = j+1
if j != 0:
bkop(l)
bkop(l)
print l
EDIT2: 好的,所以我按照你的建议修正了 bkop :
print bkop(l)
def bkop(l):
j = 0
for i in range(1, len(l)):
if l[i] < l[parent(i)]:
l[i], l[parent(i)] = l[parent(i)], l[i]
j = j+1
if j != 0:
bkop(l)
bkop(l)
print bkop(l)
但是当我运行它时,我首先得到一个随机生成的表(我应该这样),而不是min-heap表,我得到 None 值,如下所示:
[34, 9, 94, 69, 77, 33, 56]
None
有什么想法吗?也许我应该采取另一种方式,而不是将l [i]与父母进行比较,而是将l [i]与左右儿童进行比较?
答案 0 :(得分:2)
所以我在Wombatz的帮助下完成了整个工作(非常感谢!)。以下是未来用户的工作代码:
from random import randint
def parent(i):
x = i + 1
y = x//2
return y-1
def lchild(i):
x = i + 1
y = x*2
return y-1
def rchild(i):
x = i + 1
y = x*2 + 1
return y-1
l = []
dl = int(input())
for i in range (0, dl):
x = int(randint(1,100))
l.append(x)
print l
def bkop(l):
j = 0
for i in range(1, len(l)):
if l[i] < l[parent(i)]:
l[i], l[parent(i)] = l[parent(i)], l[i]
j = j+1
if j != 0:
bkop(l)
bkop(l)
print l
运行时,我已经为列表长度输入了13,我得到了结果:
13
[30, 62, 9, 100, 75, 73, 57, 82, 2, 76, 2, 50, 41] #before heapify
[2, 2, 30, 62, 9, 41, 57, 100, 82, 76, 75, 73, 50] #after heapify
答案 1 :(得分:1)
起初:您的parent
,lchild
和rchild
功能存在问题:
l[index]
获取给定索引的值。
l.index(...)
获取给定值的索引。
您正在尝试获取特定索引处的值的索引。这就像x + 1 - 1
。如果您的项目是唯一的,则该计算的索引将始终与您开始使用的索引相同。当存在重复时,您的函数将计算该索引处第一次出现的父,左和右子项。
这可能不是你想要的。因此,请将x
设置为i
或完全删除x
。
实际问题如下:
您的parent
,lchild
和rchild
函数可以在index
上运行,但您在l
处传递i
的值函数:parent(l[i])
由于列表中的值可能远高于可能的索引范围,因此列表索引超出范围。您可能希望直接传递索引。
<强>此外:强>
parent
,lchild
和rchild
返回的值不正确。在没有其他所有东西的情况下测试这些功能!
我认为结果应如下所示:
parent(1) == parent(2) == 0
lchild(0) == 1
rchild(0) == 2
您的定义会返回不同的值。
一些小事:
int
演员都没用。将int
投射到int
不会做任何事情。真正需要强制转换的唯一一行是:``dl = int(input)`int(math.floor(x/2))
。使用整数除法x // 2
代替int(math.floor(x*2))
。整数倍2是整数。无需floor
它。 修改强>
您的bkop
功能有两个问题。
l[i] < parent(i)
您可以将值与索引进行比较。我想你想将i
的值设置为其父值,而不是父索引。i == 0
,您将索引0
的值与parent(0) == -1
的值进行比较。这包裹在列表中,可能不是你想要的。由于索引0
没有父级,因此您不应尝试将其与其父级进行比较。<强> EDIT2 强>
bkop
不会返回列表,而是将其就地修改。最后只需print(l)
。您将看到原始列表已被修改。