QuickSort (the effect of different pivot)

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()

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章