Reputation: 799
I have attempted to create an insertion sort in python, however the list returned is not sorted. What is the problem with my code?
Argument given: [3, 2, 1, 4, 5, 8, 7, 9, 6]
Result: 2 1 3 6 4 7 5 8 9
Python code:
def insertion_sort(mylist):
sorted_list = []
for i in mylist:
posfound = 0 #defaults to 0
for j in range(len(sorted_list)):
if sorted_list[j] > i:
sorted_list.insert(j-1, i) #put the number in before element 'j'
posfound = 1 #if you found the correct position in the list set to 1
break
if posfound == 0: #if you can't find a place in the list
sorted_list.insert(len(sorted_list), i) #put number at the end of the list
return sorted_list
Upvotes: 2
Views: 175
Reputation: 55499
As Efferalgan & tzaman have mentioned your core problem is due to an off-by-one error. To catch these sorts of errors it's useful to print i
, j
and sorted_list
on each loop iteration to make sure they contain what you think they contain.
Here are a few versions of your algorithm. First, a repaired version of your code that fixes the off-by-one error; it also implements Efferalgan's suggestion of using .append
if an insertion position isn't found.
def insertion_sort(mylist):
sorted_list = []
for i in mylist:
posfound = 0 #defaults to 0
for j in range(len(sorted_list)):
if sorted_list[j] > i:
sorted_list.insert(j, i) #put the number in before element 'j'
posfound = 1 #if you found the correct position in the list set to 1
break
if posfound == 0: #if you can't find a place in the list
sorted_list.append(i) #put number at the end of the list
return sorted_list
Here's a slightly improved version that uses an else
clause on the loop instead of the posfound
flag; it also uses slice assignment to do the insertion.
def insertion_sort(mylist):
sorted_list = []
for i in mylist:
for j in range(len(sorted_list)):
if sorted_list[j] > i:
sorted_list[j:j] = [i]
break
else: #if you can't find a place in the list
sorted_list.append(i) #put number at the end of the list
return sorted_list
Finally, a version that uses enumerate
to get the indices and items in sorted_list
rather than a simple range
loop.
def insertion_sort(mylist):
sorted_list = []
for u in mylist:
for j, v in enumerate(sorted_list):
if v > u:
sorted_list[j:j] = [u]
break
else: #if you can't find a place in the list
sorted_list.append(u) #put number at the end of the list
return sorted_list
Upvotes: 2
Reputation: 1701
As often, it was a off-by-one error, the code below is fixed. I also made some parts a bit prettier.
def insertion_sort(mylist):
sorted_list = []
for i in mylist:
for index, j in enumerate(sorted_list):
if j > i:
sorted_list.insert(index, i) #put the number in before element 'j'
break
else:
sorted_list.append(i) #put number at the end of the list
return sorted_list
Upvotes: 1
Reputation: 47850
You need to change sorted_list.insert(j-1, i)
to be sorted_list.insert(j, i)
to insert before position j
.
insert(j-1, ..)
will insert before the previous element, and in the case where j=0
it'll wrap around and insert before the last element.
The Python data structures tutorial may be useful.
Upvotes: 4