# author Ttssxuan
# chapter 7.1
# the quicksort algorithm
def quicksort(arr, p, r):
'''
using the quicksort algorithm to sort the arr[p..r]
Parameters:
arr - the array need to be sorted
p - the beginning index
r - the ending index
Returns:
none
'''
if p < r:
# get the partition point of the arr
q = partition(arr, p, r)
# sort the left part
quicksort(arr, p, q - 1)
# sort the right part
quicksort(arr, q + 1, r)
def partition(arr, p, r):
'''
divide the arr[p..r] into two parts, the left less than arr[r], the right
greater than the arr[r]
Parameters:
arr - the array need to be sorted
p - the beginning index
r - the ending index
Returns:
the partition place of the arr
'''
x = arr[r]
i = p - 1
# divide the arr
for j in range(p, r):
if arr[j] <= x:
i += 1
arr[i], arr[j] = arr[j], arr[i]
# exchange the arr[r] to the right position
arr[i + 1], arr[r] = arr[r], arr[i + 1]
return i + 1
def partition_same_optimize(arr, p, r):
'''
divide the arr[p..r] into two parts, the left less than arr[r], the right
greater than the arr[r]
this optimize the the result when all elements in the arr[p..r] is the same
Parameters:
arr - the array need to be sorted
p - the beginning index
r - the ending index
Returns:
the partition place of the arr
'''
x = arr[r]
i = p - 1
# divide the arr
for j in range(p, r):
if arr[j] <= x:
i += 1
arr[i], arr[j] = arr[j], arr[i]
# exchange the arr[r] to the right position
if arr[p] == arr[r-1] == arr[r]:
return (p + r) >> 1
else:
arr[i + 1], arr[r] = arr[r], arr[i + 1]
return i + 1
def quicksort_nonincreasing(arr, p, r):
'''
using the quicksort algorithm to sort the arr[p..r]
this is the nonincrease version
Parameters:
arr - the array need to be sorted
p - the beginning index
r - the ending index
Returns:
none
'''
if p < r:
# get the partition point of the arr
q = partition_nonincreasing(arr, p, r)
# sort the left part
quicksort_nonincreasing(arr, p, q - 1)
# sort the right part
quicksort_nonincreasing(arr, q + 1, r)
def partition_nonincreasing(arr, p, r):
'''
divide the arr[p..r] into two parts, the left less than arr[r], the right
greater than the arr[r]
this is the nonincrease version
Parameters:
arr - the array need to be sorted
p - the beginning index
r - the ending index
Returns:
the partition place of the arr
'''
x = arr[r]
i = p - 1
# divide the arr
for j in range(p, r):
if arr[j] >= x:
i += 1
arr[i], arr[j] = arr[j], arr[i]
# exchange the arr[r] to the right position
arr[i + 1], arr[r] = arr[r], arr[i + 1]
return i + 1
def randomized_partition(arr, p, r):
'''
randomized the partition by exchange arr[r] with a random place
Parameters:
arr - the array need to be sorted
p - the beginning index
r - the ending index
Returns:
the partition place of the arr
'''
import random
# exchange arr[r] with a random place in the arr[p..r]≈
i = random.randint(p, r)
arr[r], arr[i] = arr[i], arr[r]
return partition(arr, p, r)
def randomized_quicksort(arr, p, r):
'''
quicksort the arr with randomize method
Parameters:
arr - the array need to be sorted
p - the beginning index
r - the ending index
Returns:
none
'''
if p < r:
q = randomized_partition(arr, p, r)
randomized_quicksort(arr, p, q - 1)
randomized_quicksort(arr, q + 1, r)
# test quicksort
arr = [1, 0, 2, 4, 4, 9, 9]
quicksort(arr, 0, len(arr) - 1)
print(arr)
# test quicksort_nonincreasing
quicksort_nonincreasing(arr, 0, len(arr) - 1)
print(arr)
# test randomized_quicksort
randomized_quicksort(arr, 0, len(arr) - 1)
print(arr)
# author Ttssxuan
# chapter 7.1
# the quicksort algorithm which consider that there are element identical
def partition_with_identical(arr, p, r):
'''
divide the arr[p..r] into two parts, the left less than arr[r], the right
greater than the arr[r]
Parameters:
arr - the array need to be sorted
p - the beginning index
r - the ending index
Returns:
the partition place of the arr, q and t.
all elements of arr[q..t] are equal
each elements of arr[p..q - 1] is less than arr[q]
each elements of arr[t + 1..r] is greater than arr[q]
'''
x = arr[r]
i = p - 1
t = p - 1
# divide the arr
for j in range(p, r):
# exchange with arr[t + 1], for that arr[t + 1] >= x
if arr[j] <= x:
t += 1
arr[t], arr[j] = arr[j], arr[t]
# exchange with arr[i + 1], for that arr[i + 1] >= x
if arr[t] < x:
i += 1
arr[i], arr[t] = arr[t], arr[i]
# exchange the arr[r] to the right position
arr[t + 1], arr[r] = arr[r], arr[t + 1]
return i + 1, t + 1
def randomized_partition(arr, p, r):
'''
randomized the partition by exchange arr[r] with a random place
Parameters:
arr - the array need to be sorted
p - the beginning index
r - the ending index
Returns:
the partition place of the arr
'''
import random
# exchange arr[r] with a random place in the arr[p..r]≈
i = random.randint(p, r)
arr[r], arr[i] = arr[i], arr[r]
return partition_with_identical(arr, p, r)
def randomized_quicksort(arr, p, r):
'''
quicksort the arr with randomize method
Parameters:
arr - the array need to be sorted
p - the beginning index
r - the ending index
Returns:
none
'''
if p < r:
q, t = randomized_partition(arr, p, r)
randomized_quicksort(arr, p, q - 1)
randomized_quicksort(arr, t + 1, r)
# test quicksort
arr = [1, 0, 2, 4, 4, 9, 9, 5, 5, 4, 10, 12, 13]
randomized_quicksort(arr, 0, len(arr) - 1)
print(arr)
# author Ttssxuan
# 7-1
# rewrite the quicksort with the hoare partition
def hoare_partition(arr, p, r):
'''
use the hoare method to patition the arr[p..r]
Parameters:
arr - the array need to be divide
p - the beginning of the arr
r - the ending of the arr
Returns:
the patition position of the array
'''
x = arr[p]
i = p - 1
j = r + 1
while True:
# find a element which less or equal x
while True:
j = j - 1
if arr[j] <= x:
break
# find a element which greater of equal x
while True:
i = i + 1
if arr[i] >= x:
break
# exchange the two
if i < j:
arr[i], arr[j] = arr[j], arr[i]
else:
return j
def quicksort(arr, p, r):
'''
quicksort the arr with the hoare method
Parameters:
arr - the array need to be sorted
p - the beginning of the index
r - the ending of the index
Returns:
the sorted array
'''
if p < r:
# get the partition position
q = hoare_partition(arr, p, r)
# sort the first part
quicksort(arr, p, q)
# sort the second part
quicksort(arr, q + 1, r)
# test
arr = [1, 8, 2, 10, 44, 0, 3, -1, 4]
quicksort(arr, 0, len(arr) - 1)
print(arr)
# author Ttssxuan
# chapter 7.1
# the quicksort algorithm which consider that there are element identical
# and use tail recursion to optimize the program
def partition_with_identical(arr, p, r):
'''
divide the arr[p..r] into two parts, the left less than arr[r], the right
greater than the arr[r]
Parameters:
arr - the array need to be sorted
p - the beginning index
r - the ending index
Returns:
the partition place of the arr, q and t.
all elements of arr[q..t] are equal
each elements of arr[p..q - 1] is less than arr[q]
each elements of arr[t + 1..r] is greater than arr[q]
'''
x = arr[r]
i = p - 1
t = p - 1
# divide the arr
for j in range(p, r):
# exchange with arr[t + 1], for that arr[t + 1] >= x
if arr[j] <= x:
t += 1
arr[t], arr[j] = arr[j], arr[t]
# exchange with arr[i + 1], for that arr[i + 1] >= x
if arr[t] < x:
i += 1
arr[i], arr[t] = arr[t], arr[i]
# exchange the arr[r] to the right position
arr[t + 1], arr[r] = arr[r], arr[t + 1]
return i + 1, t + 1
def randomized_partition(arr, p, r):
'''
randomized the partition by exchange arr[r] with a random place
Parameters:
arr - the array need to be sorted
p - the beginning index
r - the ending index
Returns:
the partition place of the arr
'''
import random
# exchange arr[r] with a random place in the arr[p..r]≈
i = random.randint(p, r)
arr[r], arr[i] = arr[i], arr[r]
return partition_with_identical(arr, p, r)
def tail_recursive_quicksort(arr, p, r):
'''
quicksort the arr with randomize method
Parameters:
arr - the array need to be sorted
p - the beginning index
r - the ending index
Returns:
none
'''
while p < r:
q, t = randomized_partition(arr, p, r)
# make the shorter part recursive
if (q - p) > (r - t):
tail_recursive_quicksort(arr, t + 1, r)
r = q - 1
else:
tail_recursive_quicksort(arr, p, q - 1)
p = t + 1
# test quicksort
arr = [1, 0, 2, 4, 4, 9, 9, 5, 5, 4, 10, 12, 13]
tail_recursive_quicksort(arr, 0, len(arr) - 1)
print(arr)
# author Ttssxuan
# 7-6
# the fuzzy sorting of intervals
def partition(arr, p, r):
'''
divide the space into three parts, the smaller, the larger, and overlap with
the main element
Parameters:
arr - the array need to be sort
p - the beginning position
r - the ending position
Returns:
the end of the smaller, and the beginning of the larger
'''
x = arr[r]
q = p - 1
t = r + 1
j = p
while j < r:
# smaller than the main element, move it ahead
if arr[j][1] < x[0]:
q += 1
arr[q], arr[j] = arr[j], arr[q]
# larger than the main element, move if back
elif arr[j][0] > x[1]:
t -= 1
arr[t], arr[j] = arr[j], arr[t]
j -= 1
j += 1
if j == t:
break
return q + 1, t - 1
def fuzzysort(arr, p, r):
'''
sort the arr
Parameters:
arr - the arr need to be sorted
p - the beginning of the array
r - the ending of the array
Returns:
the sorted array
'''
if p < r:
q, t = partition(arr, p, r)
print(q, t)
print(arr)
fuzzysort(arr, p, q - 1)
fuzzysort(arr, t + 1, r)
# test
arr = [[1, 2], [4, 5], [12, 14], [3, 6], [7, 9], [20, 24], [11, 13], [15, 17], [10, 11]]
fuzzysort(arr, 0, len(arr) - 1)
print(arr)