我的基数排序有啥问题?

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]

【讨论】:

以上是关于我的基数排序有啥问题?的主要内容,如果未能解决你的问题,请参考以下文章

基数排序 vs 计数排序 vs 桶排序。有啥不同?

基数排序:基数排序中的“组”是啥意思?

为啥我的基数排序 JAVA 实现比快速排序慢?

为啥我的基数排序 python 实现比快速排序慢?

基数排序浮点数

为啥 R 使用基数排序?