What is the difference if we choose the first element, or the last element, or the mid one of the (array[lo], array[hi], array[(lo + hi) / 2]) as the pivot?
Given 1000 integer numbers which need to be sorted, we compares the effect of how the pivot choice can effect the efficiency of the quick-sort algorithm.
The core algorithm is the same. The key is: remember to swap the pivot element with the first element each time, (since we are most familiar with this condition )and then start the recursion.
1. The first element as pivot.
cnt_compares = 0
cnt_swap = 0
##arr[lo] is the first element, arr[hi] is the last one
def quicksort(arr,lo,hi):
global cnt_compares, cnt_swap
if lo >= hi:
return
q = arr[lo]
i = lo + 1
for j in range(i, hi+1):## the range of j is i<=j<=hi, covers arr[i] to arr[hi]
cnt_compares += 1
if arr[j] < q: ##when i == j, we donot need do swap
cnt_swap += 1
arr[i], arr[j] = arr[j], arr[i]
i += 1 ## if the first element is the biggest one, then i == j all the time
#print arr, 'i = ', i, 'arr[lo] = ', arr[lo]
arr[i-1], arr[lo] = arr[lo], arr[i-1]
## at this time, the arr[i-1] find its correct position.
## so we recursively call the quicksort at [lo to i-2] and [i to hi]
quicksort(arr, lo, i-2)
quicksort(arr, i, hi)
#print cnt_compares
def test():
arr = []
fhand = open('QuickSort.txt')
for line in fhand:
line.strip()
arr.append(int(line))
print arr
#x = int(fhand.readline())
print 'length of arr:',len(arr)
quicksort(arr, 0, len(arr)-1) ## len(arr)-1 == hi, is the last element
print arr
print cnt_compares
print cnt_swap
if __name__ == '__main__':
test()
2. The last element as pivot
cnt_compares = 0
cnt_swap = 0
##arr[lo] is the first element, arr[hi] is the last one
def quicksort(arr,lo,hi):
global cnt_compares, cnt_swap
if lo >= hi:
return
#q = arr[lo]
q = arr[hi]
arr[hi],arr[lo]= arr[lo],arr[hi]
i = lo+1
for j in range(i, hi+1):## the range of j is i<=j<=hi, covers arr[i] to arr[hi]
cnt_compares += 1
if arr[j] < q: ##when i == j, we donot need do swap
cnt_swap += 1
arr[i], arr[j] = arr[j], arr[i]
i += 1 ## if the first element is the biggest one, then i == j all the time
#print arr, 'i = ', i, 'arr[lo] = ', arr[lo]
arr[i-1], arr[lo] = arr[lo], arr[i-1]
## at this time, the arr[i-1] find its correct position.
## so we recursively call the quicksort at [lo to i-2] and [i to hi]
quicksort(arr, lo, i-2)
quicksort(arr, i, hi)
#print arr
#print lo, i-2, hi
#print cnt_compare
def test():
arr = []
fhand = open('QuickSort.txt')
for line in fhand:
line.strip()
arr.append(int(line))
print arr
#x = int(fhand.readline())
print 'length of arr:',len(arr)
quicksort(arr, 0, len(arr)-1) ## len(arr)-1 == hi, is the last element
print arr
print cnt_compares
print cnt_swap
if __name__ == '__main__':
test()
3. The medium of the three (array[lo], array[hi], array[(lo + hi) / 2]) as the pivot.
cnt_compares = 0 # how many time of comparing?
cnt_swap = 0 # how many time of swap?
## a function to find the mid one among 3 elements
def find_mid(a, b, c):
if a > b:
a,b = b,a
if b >c:
b,c = c,b
if a < b:
return b
return a
##arr[lo] is the first element, arr[hi] is the last one
def quicksort(arr,lo,hi):
global cnt_compares, cnt_swap
if lo >= hi:
return
## from the three elements, pick the mid one as pivot
mid = (lo + hi)/2
q = find_mid(arr[lo], arr[hi], arr[mid])
## then swap the mid element with the first element
if q == arr[hi]:
arr[lo], arr[hi] = arr[hi], arr[lo]
elif q == arr[mid]:
arr[lo],arr[mid] = arr[mid],arr[lo]
i = lo + 1
for j in range(i, hi+1):## the range of j is i<=j<=hi, covers arr[i] to arr[hi]
cnt_compares += 1
if arr[j] < q: ##when i == j, we donot need do swap
cnt_swap += 1
arr[i], arr[j] = arr[j], arr[i]
i += 1 ## if the first element is the biggest one, then i == j all the time
arr[i-1], arr[lo] = arr[lo], arr[i-1]
## at this time, the arr[i-1] find its correct position.
## so we recursively call the quicksort at [lo to i-2] and [i to hi]
quicksort(arr, lo, i-2)
quicksort(arr, i, hi)
def test():
arr = []
fhand = open('QuickSort.txt') ##QuickSort.txt includes 10000 elements in a random order
for line in fhand:
line.strip()
arr.append(int(line))
print 'length of arr:',len(arr)
quicksort(arr, 0, len(arr)-1) ## len(arr)-1 == hi, is the last element
print arr
print cnt_compares
print cnt_swap
if __name__ == '__main__':
test()