# author Ttssxuan
# this is the sample of the selection sort
def selection_sort(arr):
'''selection sort.
arr: the arr you want to sort'''
# find the ith element of the arr
for i in range(0, len(arr) - 1):
min = i
# find the min element in rest
for j in range(i + 1, len(arr)):
if arr[j] < arr[min]:
min = j
#swap the ith element to the ith position
temp = arr[min]
arr[min] = arr[i]
arr[i] = temp
#test
arr = [2, 4, 5, 9, 4]
selection_sort(arr)
print(str(arr))
# author Ttssxuan
# Insertion sort, sort the arr with ascent order
def insertion_sort(arr):
'''Insertion_sort, arr: the input arr that we want to sort'''
# scan every element of the arr and find the properly place for it
for j in range(1, len(arr)):
key = arr[j]
i = j - 1
# scan the sorted subarray arr[0..j -1], find the proper place
while(i >= 0 and key < arr[i]):
arr[i + 1] = arr[i]
i = i - 1
arr[i + 1] = key
# test
arr = [6, 2, 3, 4, 5]
insertion_sort(arr)
print(str(arr))
# author Ttssxuan
# Chapter 2
# merge sort, the provide two kinds of method to merge the two sequece.
from math import floor
def Merge(arr, p, q, e):
'''The merge, arr:the array need to merge, p:the start place of the first
part, q:the end of the first part, e:the end of the sencond merge part.
This is the version of with sentinel.'''
n1 = q - p + 1
n2 = e - q
l = [0] * (n1 + 1)
r = [0] * (n2 + 1)
# copy the first part from the initial arr
for i in range(0, n1):
l[i] = arr[p + i]
# copy the second part from the initial arr
for j in range(0, n2):
r[j] = arr[q + j + 1]
# set the sentinel of the two part
l[n1] = 10000
r[n2] = 10000
i = 0
j = 0
# merge the two part to arr
for k in range(p, e):
if l[i] <= r[j]:
arr[k] = l[i]
i += 1
else:
arr[k] = r[j]
j += 1
def Merge_no_sentinel(arr, p, q, e):
'''The merge, arr:the array need to merge, p:the start place of the first
part, q:the end of the first part, e:the end of the sencond merge part.
This is the version of without sentinel'''
n1 = q - p + 1
n2 = e - q
l = [0] * n1
r = [0] * n2
# copy the first part from the initail arr
for i in range(0, n1):
l[i] = arr[p + i]
# copy the second pary from the initail arr
for j in range(0, n2):
r[j] = arr[q + j + 1]
i = 0
j = 0
# merge the two part until one of the two part encount the end
for k in range(p, e + 1):
if (i < n1 and j < n2):
if l[i] <= r[j]:
arr[k] = l[i]
i += 1
else:
arr[k] = r[j]
j += 1
else:
break
# copy the rest of the two part to the initail arr
if i < n1:
while k <= e:
arr[k] = l[i]
k += 1
i += 1
if j < n2:
while k <= e:
arr[k] = r[j]
k += 1
j += 1
def Merge_sort(arr, s, e):
'''Use merge sort algorithm to sort the arr, and the start position is s,
the end position is e.'''
if s != e:
# get the middle of the arr for s to e
mid = int(floor((s + e) / 2))
# merge sort the first part
Merge_sort(arr, s, mid)
# merge sort the second part
Merge_sort(arr, mid + 1, e)
# merge the tow part
Merge_no_sentinel(arr, s, mid, e)
#test
arr = [1, 3, 5, 2, 4, 6]
Merge_sort(arr, 0, len(arr) - 1)
print(str(arr))
# author Ttssxuan
# 2.3-5
# binary search
import math
def binary_search(arr, value, s, e):
'''arr:input, value:the value you wanted, s: start place in the arr, e:the
end place in the arr
if no such value RETURN -1, else RETURN the place of the value'''
if s > e:
return -1
else:
# get the middle of the index
mid = int(math.floor((s + e) / 2))
# judge the mid is equal the value
if arr[mid] == value:
return mid
# search the first half
elif arr[mid] > value:
return binary_search(arr, value, s, mid - 1)
# search the second half
else:
return binary_search(arr, value, mid + 1, e)
# test
arr = [1, 2, 3, 4, 5]
place = binary_search(arr, 1, 0, len(arr) - 1)
if place != -1:
print("the place is ", place)
else:
print("no such value")
# author Ttssxuan
# 2.3-7
# Describe a ‚.n lg n/-time algorithm that, given a set S of n integers
# and another integer x, determines whether or not there exist two
# elements in S whose sum is exactly x.
from math import floor
import math
def Merge_no_sentinel(arr, p, q, e):
'''The merge, arr:the array need to merge, p:the start place of the first
part, q:the end of the first part, e:the end of the sencond merge part.
This is the version of without sentinel'''
n1 = q - p + 1
n2 = e - q
l = [0] * n1
r = [0] * n2
# copy the first part from the initail arr
for i in range(0, n1):
l[i] = arr[p + i]
# copy the second pary from the initail arr
for j in range(0, n2):
r[j] = arr[q + j + 1]
i = 0
j = 0
# merge the two part until one of the two part encount the end
for k in range(p, e + 1):
if (i < n1 and j < n2):
if l[i] <= r[j]:
arr[k] = l[i]
i += 1
else:
arr[k] = r[j]
j += 1
else:
break
# copy the rest of the two part to the initail arr
if i < n1:
while k <= e:
arr[k] = l[i]
k += 1
i += 1
if j < n2:
while k <= e:
arr[k] = r[j]
k += 1
j += 1
def Merge_sort(arr, s, e):
'''Use merge sort algorithm to sort the arr, and the start position is s,
the end position is e.'''
if s != e:
# get the middle of the arr for s to e
mid = int(math.floor((s + e) / 2))
# merge sort the first part
Merge_sort(arr, s, mid)
# merge sort the second part
Merge_sort(arr, mid + 1, e)
# merge the tow part
Merge_no_sentinel(arr, s, mid, e)
def binary_search(arr, value, s, e):
'''arr:input, value:the value you wanted, s: start place in the arr, e:the
end place in the arr
if no such value RETURN -1, else RETURN the place of the value'''
if s > e:
return -1
else:
mid = int(math.floor((s + e) / 2))
if arr[mid] == value:
return mid
elif arr[mid] > value:
return binary_search(arr, value, s, mid - 1)
else:
return binary_search(arr, value, mid + 1, e)
def estimate(arr, value):
'''arr: the set which you want to search, value: the value you want to
search.
Return [first, second], if get the place, the first and second present
the place of the two value, else return [-1, -1]'''
# sort the array first
Merge_sort(arr, 0, len(arr) - 1)
# search each element of the arr
for first in range(0, len(arr)):
# calculate the other of the two
rest = value - arr[first]
# use binary search verify if there is the value
second = binary_search(arr, rest, first + 1, len(arr) - 1)
if second != -1:
return [first, second]
return [-1, -1]
# test
arr = [1, 3, 4, 5]
print(arr)
result = estimate(arr, 10)
print(result)
result = estimate(arr, 4)
print(result)
result = estimate(arr, -1)
print(result)
# author Ttssxuan
# Problem 2-2
# bubblesort
def bubble_sort(arr):
# total rearrange len(arr) times
for i in range(0, len(arr) - 1):
# swap the min of the arr[i, len(arr) - 1] to the top
for j in range(len(arr) - 1, i, -1):
if arr[j] < arr[j - 1]:
# swap arr[j], arr[j - 1]
arr[j], arr[j - 1] = arr[j - 1], arr[j]
# test
arr = [9, 2, 5, 2, 0, 2]
bubble_sort(arr)
print(arr)
# author Ttssxuan
# Problem 2-4 d
# Give an algorithm that determines the number of inversions in any permutation
# on n elements in ‚.n lg n/ worst-case time.
# We implement it by modifying merge sort
from math import floor
def Merge_no_sentinel(arr, p, q, e):
'''The merge, arr:the array need to merge, p:the start place of the first
part, q:the end of the first part, e:the end of the sencond merge part.
This is the version of without sentinel
return the inversion number of this merge'''
n1 = q - p + 1
n2 = e - q
l = [0] * n1
r = [0] * n2
# copy the first part from the initail arr
for i in range(0, n1):
l[i] = arr[p + i]
# copy the second pary from the initail arr
for j in range(0, n2):
r[j] = arr[q + j + 1]
# recorder the total number of inversion
inversion_number = 0
# recorder the number of the numbers in array "r" which was added in "arr"
count = 0
i = 0
j = 0
# Merge the two part until one of the two part encount the end.
# We know that if the number in ther array "l" less than the number in the
# array "r", the pair of the number is not inversion, so we just count the
# number in array "r" which added in the "arr" before the number in array
# "l". Each this occur, we know there is inversion.
for k in range(p, e + 1):
if (i < n1 and j < n2):
if l[i] <= r[j]:
arr[k] = l[i]
i += 1
# add the inversion for this number
inversion_number += count
else:
arr[k] = r[j]
j += 1
# increase the number which was added in "arr"
count += 1
else:
break
# copy the rest of the two part to the initail arr
if j < n2:
while k <= e:
arr[k] = r[j]
k += 1
j += 1
if i < n1:
while k <= e:
arr[k] = l[i]
k += 1
i += 1
# add the inversion for this number
inversion_number += count
return inversion_number
def Merge_sort(arr, s, e):
'''Use merge sort algorithm to sort the arr, and the start position is s,
the end position is e.
return the inversion number of the arr'''
inversion_number = 0
if s != e:
# get the middle of the arr for s to e
mid = int(floor((s + e) / 2))
# merge sort the first part
inversion_number += Merge_sort(arr, s, mid)
# merge sort the second part
inversion_number += Merge_sort(arr, mid + 1, e)
# merge the tow part
inversion_number += Merge_no_sentinel(arr, s, mid, e)
return inversion_number
def count_inversion(arr):
'''count the inversion number of a sequence, which was implement by change
the merge sort
arr: the sequence we want to count
return the inversion number of the sequence.'''
return Merge_sort(arr, 0, len(arr) - 1)
#test
arr = [1, 2, 0, -1]
re = count_inversion(arr)
print re
arr = [0, 1, 2, 3]
re = count_inversion(arr)
print re
arr = [5, 4, 3, 2, 1]
re = count_inversion(arr)
print re