Question

Note: I am using python 3.

I am trying to sort a list of words in alphabetical order.

This is my sort:

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)

It is being used in this loop:

for x in range(0,maxL):
    radix_sort(results[x], x)

maxL is the length of the longest words I have, so iterating from 0 to maxL goes through the entire list.

My list results[] is a list of lists. Each list within results contains a word object described as follows:

class word(object): #object class

    def __init__(self, originalWord=None, azWord=None, wLength=None):
        self.originalWord = originalWord
        self.azWord = azWord
        self.wLength = wLength

For example, results[3] should contain a list of all words with wLength of 3.

When I feed my entire program the following input:

hello
world
alphabetical
dog
cat
potato
stack

With this piece of code:

for row in results:
    for item in row:
        print(item.originalWord)

It prints:

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

I'm pretty sure I'm iterating through results[] correctly when printing. Why is my radix_sort not giving me the right results? I tried using the debugger but no luck.

EDIT: I changed my code to be as follows:

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

Now it's giving me an error here:

for containedList in buckets:

It says "UnboundLocalError: local variable 'buckets' referenced before assignment". What does this mean?

Was it helpful?

Solution

Following on my comments, that should look like

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)

OTHER TIPS

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

Let's take a look at this code. On the first iteration of the outer loop, you put all the words in the buckets. On the second iteration, you put all the words in the buckets again. That happens again and again on every further iteration; only once you're all done do you take the words out of the buckets and put them back in the original list.

In radix sort, when you sort, you need to create a fresh set of buckets on every iteration of the outer loop. Every time you finish putting the items in the buckets, you need to reorder the list using the buckets, rather than doing that only at the very end.

Use a list comprehension when making your queue. This will make your code easier to read, as nobody wants to count all those empty bins.

buckets = [[] for i in range(26)]

Also, another way to get the bucket index, instead of assigning a variable, just put those calculations in the index.

buckets[((ord(letter)/10**i)%10) for letter in word]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top