我的基数排序有啥问题?
Posted
技术标签:
【中文标题】我的基数排序有啥问题?【英文标题】:What is wrong with my radix sort?我的基数排序有什么问题? 【发布时间】:2014-04-03 17:21:44 【问题描述】:注意:我使用的是 python 3。
我正在尝试按字母顺序对单词列表进行排序。
这是我喜欢的类型:
def radix_sort(List, length):
buckets = [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []]
for i in range (length-1, -1, -1): #for every letter "column"
for word in List: #for every word
index = ord(word.azWord[i])-ord('a') #get the index of the word
buckets[index].append(word) #add word object to correct bucket
List[:] = []
for containedList in buckets:
List.extend(containedList)
它正在这个循环中使用:
for x in range(0,maxL):
radix_sort(results[x], x)
maxL 是我拥有的最长单词的长度,因此从 0 迭代到 maxL 会遍历整个列表。
我的列表结果[] 是一个列表列表。结果中的每个列表都包含一个单词对象,描述如下:
class word(object): #object class
def __init__(self, originalWord=None, azWord=None, wLength=None):
self.originalWord = originalWord
self.azWord = azWord
self.wLength = wLength
例如,results[3] 应该包含 wLength 为 3 的所有单词的列表。
当我为整个程序提供以下输入时:
hello
world
alphabetical
dog
cat
potato
stack
有了这段代码:
for row in results:
for item in row:
print(item.originalWord)
打印出来:
cat
cat
dog
dog
dog
cat
stack
stack
world
hello
hello
stack
hello
hello
world
hello
world
world
stack
stack
world
potato
potato
potato
potato
potato
potato
alphabetical
我很确定我在打印时正确地遍历了 results[]。为什么我的 radix_sort 没有给我正确的结果?我尝试使用调试器,但没有成功。
编辑:我将代码更改为如下:
def radix_sort(List, length):
for i in range (length-1, -1, -1):
for word in List:
buckets = [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []]
index = ord(word.azWord[i])-ord('a')
buckets[index].append(word)
List[:] = []
for containedList in buckets:
List.extend(containedList)
return List #returns an alphabetized list
现在这里给我一个错误:
for containedList in buckets:
它说“UnboundLocalError:分配前引用的局部变量'buckets'”。这是什么意思?
【问题讨论】:
buckets[index].append(word)
您将每个单词 length
次附加到存储桶中。
天哪。你是对的。
基本上,您需要将buckets
创建移动到第一个循环中,以及List
重建。
如果我只是将List[:] = []
推入for word in List
循环,它似乎工作正常。有什么理由我应该移动我丢失的buckets
?
看我的回答。你的 buckets 声明现在循环太深了,你的 List 重建没有移动。
【参考方案1】:
按照我的 cmets,应该是这样的
def radix_sort(List, length):
for i in range (length-1, -1, -1): #for every letter "column"
# Here buckets are created for each iteration
buckets = [[], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], [], []]
for word in List: #for every word
index = ord(word.azWord[i])-ord('a') #get the index of the word
buckets[index].append(word) #add word object to correct bucket
# Here List is reconstructed for each iteration
List[:] = []
for containedList in buckets:
List.extend(containedList)
【讨论】:
我明白了。我现在知道我哪里出错了。非常感谢。【参考方案2】:for i in range (length-1, -1, -1): #for every letter "column"
for word in List: #for every word
index = ord(word.azWord[i])-ord('a') #get the index of the word
buckets[index].append(word) #add word object to correct bucket
让我们看一下这段代码。在外部循环的第一次迭代中,您将所有单词放入桶中。在第二次迭代中,您将所有单词再次放入桶中。在每一次进一步的迭代中,这种情况一次又一次地发生;只有当你全部完成后,你才能从桶中取出单词并将它们放回原始列表中。
在基数排序中,当您进行排序时,您需要在外循环的每次迭代中创建一组新的桶。每次完成将项目放入存储桶时,您都需要使用存储桶重新排序列表,而不是仅在最后才这样做。
【讨论】:
啊哈!我错过了将List[:] = []
缩进一点到for word in List
循环中。这解决了问题。谢谢!
@Michi:看起来你已经解决了问题,但从你的描述来看,你似乎只是改变了问题的表现方式。
我不明白,你能解释一下你的意思吗?另外,请参阅我上面的编辑。好像还是有问题。
@Michi:您将存储桶创建和列表清空部分移得太深,并且您没有更改需要的部分。需要重新创建存储桶,并在外循环的每次迭代中重新排序列表。目前,您正在重新创建存储桶并在内循环的每次迭代中清空列表,并且您只是在最后而不是在清空列表后立即将项目放回列表中。【参考方案3】:
在制作队列时使用列表推导式。这将使您的代码更易于阅读,因为没有人愿意计算所有这些空垃圾箱。
buckets = [[] for i in range(26)]
另外,另一种获取桶索引的方法,而不是分配变量,只需将这些计算放入索引中即可。
buckets[((ord(letter)/10**i)%10) for letter in word]
【讨论】:
以上是关于我的基数排序有啥问题?的主要内容,如果未能解决你的问题,请参考以下文章