5
\$\begingroup\$

I'm learning basic algorithms and implementing them in Python. Critiques needed/welcome.

import pudb; pu.db
import random
def selection_sort(list_):
 """Implement selection_sort algorithm: iterate L to R in list, grab value
 if greatest and inserting into correct pos. After each loop, decrement
 length of iterated list by 1"""
 val_list, greatest = list(range(len(list_))), 0
 for num in range(len(list_)):
 greatest = val_list[-1]
 for val in val_list:
 if list_[greatest] < list_[val]:
 greatest = val
 if list_[greatest] > list_[val_list[-1]]:
 list_.insert(val, list_.pop(greatest))
 val_list.remove(val)
 return list_
if __name__ == '__main__':
 unsorted = list(range(9))
 random.shuffle(unsorted)
 assert selection_sort(unsorted) == list(range(9))
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Feb 3, 2014 at 12:56
\$\endgroup\$

1 Answer 1

11
\$\begingroup\$

Most of my comments on your previous question apply here too, so I'll just summarize them quickly:

  1. Debugging code that you forgot to remove.

  2. Docstring written from the implementer's point of view.

  3. Variable name respelled to avoid shadowing a built-in.

  4. Test case not organized into a unit test.

  5. Test case not very stringent (just 9 items).

In addition:

  1. Given an array of length n, your algorithm makes n passes over the array, and in pass i it finds the ith largest item in the array (which at that point in the algorithm is the largest item in the first ni positions) and swaps it into the position ni − 1. This ought to be simple, but it's implemented in a very complex way, via the list val_list of indexes.

    Here's a much simpler implementation:

    def selection_sort(seq):
     """Sort the mutable sequence seq in place and return it."""
     for i in reversed(range(len(seq))):
     # Find the index of greatest item in seq[:i+1].
     greatest = 0
     for j in range(1, i + 1):
     if seq[j] > seq[greatest]:
     greatest = j
     seq[i], seq[greatest] = seq[greatest], seq[i]
     return seq
    

    Note that I've avoided testing seq[greatest] > seq[i] before doing the swap, because I know that the only way this condition can fail is if greatest == i, and then the swap has no effect. So it's simplest to skip the test.

    I could simplify this still further using Python's built-in function max:

    def selection_sort(seq):
     """Sort the mutable sequence seq in place and return it."""
     for i in reversed(range(len(seq))):
     greatest = max(range(i + 1), key=seq.__getitem__)
     seq[i], seq[greatest] = seq[greatest], seq[i]
     return seq
    

    But this seems like it's avoiding the spirit of the exercise: I mean, if I can use max, then why not sorted?

answered Feb 3, 2014 at 14:25
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.