Related
I'm trying to implement a recursive quicksort algorithm using two methods (swap, partition) while running the main algorithm using recursion in a lambda expression. I'm getting an infinite recursion error and honestly I can't find the syntax error. Can someone help me out? Thanks :)
def swap(array, a, b):
array[a], array[b] = array[b], array[a]
def partition(array, high, low):
pivot = array[high]
i = low
for x in range(low, high-1):
if array[x] < pivot:
i+=1
swap(array, array[x], array[high])
return i
g = lambda array, low, high: g(array,low,partition(array,high,low)-1)+g(array,partition(array,high,low)+1,high) if low < high else print("not sorted")
There are several issues in partition:
The call to swap is passing values from your list, instead of indices.
Even when the previous mistake is corrected, it will either move the pivot value to the low+1 index, or it will not move at all.
The returned index i, should be the one where the pivot was moved. In a correct implementation that means i is the last index to which a value was moved, which was the value at index high. This is not what is happening, as already with the first swap the pivot value is moved.
The swap should be of the current value with the value at i, so that all values up to the one at index i are less or equal to the pivot value.
Here is the corrected partition function:
def partition(array, high, low):
pivot = array[high]
i = low - 1
for x in range(low, high+1):
if array[x] <= pivot:
i+=1
swap(array, x, i)
return i
These are the issues in the function g:
It is supposed to perform the sort in-place, so the + operator for lists should not occur here, as that would create a new list. Moreover, the base case (in else) does not return anything, so the + operator will fail with an error
partition(array,high,low) is called twice, which is not only a waste, but the second call will in most cases return a different result, because the pivot can be different. This means the second call of g will potentially not work with an adjacent partition, but will either leave an (unsorted) gap, or work on an overlapping partition.
Here is a correction for the function g:
def g(array, low, high):
if low < high:
i = partition(array, high, low)
g(array, low, i-1)
g(array, i+1, high)
You should also consider using a better name than g, and change the order of the high/low parameters for partition: that reversed order is a good way to confuse the readers of your code.
Here is Hoare's quicksort algorithm implemented in Python -
def quicksort(A, lo, hi):
if lo >= 0 and hi >= 0 and lo < hi:
p = partition(A, lo, hi)
quicksort(A, lo, p)
quicksort(A, p + 1, hi)
def partition(A, lo, hi):
pivot = A[(hi + lo) // 2]
i = lo
j = hi
while True:
while A[i] < pivot:
i += 1
while A[j] > pivot:
j -= 1
if i >= j:
return j
swap(A, i, j)
def swap(A, i, j):
A[i], A[j] = A[j], A[i]
You can write g using lambda if you wish, but I would recommend to define an ordinary function instead -
g = lambda a: quicksort(a, 0, len(a) - 1)
Given a sample input, x -
x = [5,0,9,7,4,2,8,3,1,6]
g(x)
print(x)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
See this related Q&A if you would like to count the number of comparisons and swaps used.
def insertion_sort2(A):
for i in range(1,len(A)):
key = A[i]
j = i-1
for j in range(i-1,0,-1):
if A[j] > key :
A[j+1] = A[j]
else:
A[j+1] = key
break
for i in range(1, len(arr)):
key = arr[i]
j = i-1
while j >=0 and key < arr[j] :
arr[j+1] = arr[j]
j -= 1
arr[j+1] = key
Hello I have tried both methods to do simple Insertion Sort in c++ it works but in python it is not working,but both of them are giving answers like
1st one:
[56, 77, 77, 77, 77, 77, 77, 99]
2nd one:
does not sort even
Note:The second one starts after break and I have not run them both together,I commented out one and then run the other one
First of all you don't go upto the 0th element in the array in the inner loop. In python's range function, the range is counted uptil one before the second term. On putting range(i-1,-1,-1) the range becomes i-1 to 0.
Secondly, you are not swapping the two consecutive elements , just assigning (j)th element a value of (j+1)th element. But what about assigning jth value to (j-1)th element.
Third, there's no meaning of doing A[j+1] = key as it already is key.
def insertion_sort2(A):
for i in range(1,len(A)):
key = A[i]
j = i-1
for j in range(i-1,-1,-1):
if A[j] > key :
A[j+1], A[j] = A[j], A[j+1]
else:
break
i'm a beginning python programmer and i'm trying to write a code that sorts data in an array in increasing order as below:
A = [2,3,6,8,4,5,7,123,543,65435,31,43]
for i in range(len(A)-1):
if A[i] > A[i+1]:
A[i] , A[i+1] = A[i+1] , A[i]
print (A)
However the result returns this:
[2, 3, 6, 4, 5, 7, 8, 123, 543, 31, 43, 65435]
May I know what I'm doing wrong? Any help would be much appreciated. Thanks!
You are only performing a single stage of bubble-sort; to get the list completely sorted, you would have to float the numbers up n - 1 times, not only one.
Try this:
for i in range(len(A)-1):
for i in range(len(A)-1):
if A[i] > A[i+1]:
A[i] , A[i+1] = A[i+1] , A[i]
You are trying to do Bubble Sort. Actually the part of your code works, In your result the greatest element is at the end of the sorted array. Now you have to do the same for all remaining elements in a nested for loop. That's why Bubble Sort has the complexity of O(n^2)
A = [2,3,6,8,4,5,7,123,543,65435,31,43]
for i in range(0,len(A)):
for j in range(i+1):
if A[i] > A[j]:
A[i] , A[j] = A[j] , A[i]
print A
Sorting needs comparing an element with rest of the elements in that array
I really need your help, I am learning sorting-algorithms and i tried to make an Insertionsort-Algorithm. So could you please tell me whether this is an Insertionsort-Algorithm or not?
def insertsort(l):
for k in range(len(l)):
for i in range(1,len(l)):
if l[i]<l[i-1]:
while l[i]<l[i-1]:
l.insert(i-1,l.pop(i))
return l
yes, it is insertion sort. The pseudocode is as follows:
1. for j = 2 to n
2. key ← A [j]
3. // Insert A[j] into the sorted sequence A[1..j-1]
4. j ← i – 1
5. while i > 0 and A[i] > key
6. A[i+1] ← A[i]
7. i ← i – 1
8. A[j+1] ← key
I do not think so. You used two nested for loops and a while. In the pseudocode provided by #dreadedHarvester and the implementation provided in RosettaCode just one for loop and one while are used.
def insertion_sort(l):
for i in xrange(1, len(l)):
j = i-1
key = l[i]
while (l[j] > key) and (j >= 0):
l[j+1] = l[j]
j -= 1
l[j+1] = key
I have been trying to implement quicksort for like 2 days now (Looks like my programming skills are getting rusty). I do not know what I am doing wrong. I was about to give up so I thought I should consult the discussion forum.
here is the code that I am trying to implement in python. But it is not giving the desired result. Anyone can please point out what I am doing wrong?
def QuickSort(A,p,r):
if p < r:
pivotIndex = Partition(A,p,r)
QuickSort(A,p,pivotIndex-1)
QuickSort(A,pivotIndex+1,r)
return A
def Partition(A,p,r):
m = A[p]
i = p+1
for j in range( p+1 , r ):
if A[j] < m:
A[j] , A[i] = A[i] , A[j]
i+=1
A[p], A[i-1] = A[i-1] , A[p]
return i-1
The output for test input is:
>>>QuickSort([9,8,7,6,5,4,3,2,1],0,9)
[1, 3, 5, 6, 7, 4, 8, 2, 9]
I will be very thankful if anyone help me in implementing this.
Regards
Slicing doesn't return a view of the original list; it makes a new list out of data from the old list. That means the recursive calls to QuickSort don't change the original list.
You can try this implementation in one line of code:
def QuickSort(list):
return [] if list==[] else QuickSort([x for x in list[1:] if x < list[0]]) + [list[0]] + QuickSort([x for x in list[1:] if x >= list[0]])
print QuickSort([9,8,7,6,5,4,3,2,1])
I have figured out the answer. It appeared that I was passing one-less to the QuickSort method
def QuickSort(A,p,r):
if r-p <= 1: return
pivotIndex = Partition(A,p,r)
QuickSort(A,p,pivotIndex)
QuickSort(A,pivotIndex+1,r)
return A
def Partition(A,p,r):
m = A[p]
i = p+1
for j in range( p+1 , r ):
if A[j] < m:
A[j] , A[i] = A[i] , A[j]
i= i + 1
A[p], A[i-1] = A[i-1] , A[p]
return i-1
It is the correct implementation
It seems that you wanted to keep the pivot on the left side and skip it, but that didn't turn out well, so I just moved it to the end of the array and reduced the iteration index accordingly and then reversed the post-partition swap (to take into consideration the pivot movement).
def Partition(A,p,r):
m = A[p]
A[p], A[r] = A[r], A[p]
i = p
for j in range( p, r ):
if A[j] < m:
A[j] , A[i] = A[i] , A[j]
i+=1
A[r], A[i] = A[i] , A[r]
return i
I think that you could do it with the pivot on the left side, but then you would have to change the loop direction I guess, but I am not sure.
EDIT: Sorry I forgot to add the call is then QuickSort([9,8,7,6,5,4,3,2,1],0,8), since the indices are inclusive now.