banchan86
5/29/2017 - 2:55 PM

Quicksort with 2 way and 3 way partition (to handle equal cases)

Quicksort with 2 way and 3 way partition (to handle equal cases)

# # Uses python3
import sys
import random

def partition3(a, left, right):
    pivot = a[left]
    last_lower_element = left
    first_greater_element = right
    current_number = left
    while current_number <= first_greater_element:
        if a[current_number] < pivot:
            a[current_number], a[last_lower_element] = a[last_lower_element], a[current_number]
            last_lower_element += 1
            current_number += 1
        elif a[current_number] > pivot:
            a[current_number], a[first_greater_element] = a[first_greater_element], a[current_number]
            first_greater_element -= 1
            #if current number > pivot, we move this number to the end, shift the rightmost wall one number closer, and 
            # also stay in the current position to evaluate the current number if it continues to be bigger, shift them outward.
            # we only move on if we find a number that is smaller or equal to the current pivot.
        else:
            current_number += 1
            #if current number == pivot, we just move on to the next number
    return last_lower_element, first_greater_element

# 2 way partition will exhibit o(n2) behaviour if there are a lot of equal elements.
def partition2(a, l, r):
    x = a[l]
    j = l;
    for i in range(l + 1, r + 1):
        if a[i] <= x:
            j += 1
            a[i], a[j] = a[j], a[i]
    a[l], a[j] = a[j], a[l]
    return j


def randomized_quick_sort(a, l, r):
    if l >= r:
        return
    k = random.randint(l, r)
    a[l], a[k] = a[k], a[l]
   # partition 2 potion
   #  m = partition2(a, l, r)
   #  randomized_quick_sort(a, l, m - 1);
   #  randomized_quick_sort(a, m + 1, r);
    # partition 3 portion
    m1, m2 = partition3(a, l, r)
    randomized_quick_sort(a, l, m1 - 1);
    randomized_quick_sort(a, m2 + 1, r);


# portion for submission
if __name__ == '__main__':
    input = sys.stdin.read()
    n, *a = list(map(int, input.split()))

# test_cases for python tutor
# n = 5
# a = [2, 3, 9, 2, 9]
# n = 6
# a = [6, 5, 4, 3, 3, 3]
# n = 5
# a = [2, 3, 9, 2, 2]
# the below test case fails when there is a random pivot
# n = 8
# a = [2, 4, 3, 4, 7, 8, 9, 9]

randomized_quick_sort(a, 0, n - 1)
for x in a:
    print(x, end=' ')