# author Ttssxuan
# 6.2-5
# heapify use the loop instead of recursion
# note: To follow the Introduction of Algorithm, we use arr[0] store the
# heap_size, and the index of the element start at 1
def max_heapify(arr, i):
'''
The list struct as menthioned above.
Maintain the max-heap property use the recursive method. This function
assumes the LEFT(i) and RIGHT(i) are max-heap.
Parameters:
arr - the heap
i - the index input to the array
Returns:
none
'''
pos = i
while True:
# the left children of arr[i]
l = pos << 1
# the right children of arr[i]
r = pos << 1 | 1
#find the largest of the three
if l <= arr[0] and arr[l] > arr[pos]:
largest = l
else:
largest = pos
if r <= arr[0] and arr[r] > arr[largest]:
largest = r
# make the largest of them to the appropriate position
if largest != pos:
arr[pos], arr[largest] = arr[largest], arr[pos]
pos = largest
else:
break
# test max_heapify
print("test max_heapify")
arr = [5, 4, 6, 3, 2, 5]
max_heapify(arr, 1)
print(arr)
arr = [7, 5, 4, 7, 3, 2, 6, 3]
max_heapify(arr, 1)
print(arr)
arr = [7, 6, 5, 4, 2, 3, 3, 2]
print(arr)
def min_heapify(arr, i):
'''
The list struct as menthioned above.
Maintain the min-heap property use the recursive method. This function
assumes the LEFT(i) and RIGHT(i) are min-heap.
Parameters:
arr - the heap
i - the index input to the array
Returns:
none
'''
pos = i
while True:
# the left children of arr[i]
l = pos << 1
# the right children of arr[i]
r = pos << 1 | 1
#find the smallest of the three
if l <= arr[0] and arr[l] < arr[pos]:
smallest = l
else:
smallest = pos
if r <= arr[0] and arr[r] < arr[smallest]:
smallest = r
# make the largest of them to the appropriate position
if smallest != pos:
arr[pos], arr[smallest] = arr[smallest], arr[pos]
pos = smallest
else:
break
# test min_heapify
print("test min_heapify")
arr = [5, 3, 1, 2, 4, 2]
min_heapify(arr, 1)
print(arr)
arr = [7, 5, 2, 1, 4, 2, 3, 4]
min_heapify(arr, 1)
print(arr)
arr = [7, 2, 3, 4, 5, 6, 7, 8]
min_heapify(arr, 1)
print(arr)
# author Ttssxuan
# Chapter 6
# Heap Sort
# note: To follow the Introduction of Algorithm, we use arr[0] store the
# heap_size, and the index of the element start at 1
def max_heapify(arr, i):
'''
The list struct as menthioned above.
Maintain the max-heap property use the recursive method. This function
assumes the LEFT(i) and RIGHT(i) are max-heap.
Parameters:
arr - the heap
i - the index input to the array
Returns:
none
'''
# the left children of arr[i]
l = i << 1
# the right children of arr[i]
r = i << 1 | 1
# find the largest of the three
if l <= arr[0] and arr[l] > arr[i]:
largest = l
else:
largest = i
if r <= arr[0] and arr[r] > arr[largest]:
largest = r
# make the largest of them to the appropriate place
if largest != i:
arr[i], arr[largest] = arr[largest], arr[i]
max_heapify(arr, largest)
# test max_heapify
print("test max_heapify")
arr = [5, 4, 6, 3, 2, 5]
max_heapify(arr, 1)
print(arr)
arr = [7, 5, 4, 7, 3, 2, 6, 3]
max_heapify(arr, 1)
print(arr)
arr = [7, 6, 5, 4, 2, 3, 3, 2]
print(arr)
def min_heapify(arr, i):
'''
for 6.2-2
The list struct as menthioned above.
Maintain the min-heap property use the recursive method. This function
assumes the LEFT(i) and RIGHT(i) are min-heap.
Parameters:
arr - the heap
i - the index input to the array
Returns:
none
'''
# the left children of arr[i]
l = i << 1
# the right children of arr[i]
r = i << 1 | 1
# find the smallest of the three
if l <= arr[0] and arr[l] < arr[i]:
smallest = l
else:
smallest = i
if r <= arr[0] and arr[r] < arr[smallest]:
smallest = r
# make the smallest of the them to the appropriate place
if smallest != i:
arr[i], arr[smallest] = arr[smallest], arr[i]
min_heapify(arr, smallest)
# test min_heapify
print("test min_heapify")
arr = [5, 3, 1, 2, 4, 2]
min_heapify(arr, 1)
print(arr)
arr = [7, 5, 2, 1, 4, 2, 3, 4]
min_heapify(arr, 1)
print(arr)
arr = [7, 2, 3, 4, 5, 6, 7, 8]
min_heapify(arr, 1)
print(arr)
def build_max_heap(arr):
'''
Building a max_heap from an unordered linear array in linear time.
Parameters:
arr - the unordered linear array used to build a max_heap
Returns:
the arr[0] recorded the heap-size of the array, orthers recoder value
'''
# moving the arr[0] to the end of the array, and make the a[0] save heap_size
arr.append(arr[0])
arr[0] = len(arr) - 1
# building the max_heap use the function max_heapify
for i in range((arr[0] >> 1), 0, -1):
max_heapify(arr, i)
# test build_max_heap
print("test build_max_heap")
arr = [0, 1, 2, 4, 5, 6]
build_max_heap(arr)
print(arr)
arr = [5, 2, 4, 1, 7, 9, 10]
build_max_heap(arr)
print(arr)
arr = [10, 3, 4, 9, 11, 4, 10]
build_max_heap(arr)
print(arr)
def build_min_heap(arr):
'''
Building a min_heap from an unordered linear array in linear time.
Parameters:
arr - the unordered linear array used to build a min_heap
Returns:
the arr[0] recorded the heap-size of the array, orthers recoder value
'''
# moving the arr[0] to the end of the array, and make the a[0] save heap_size
arr.append(arr[0])
arr[0] = len(arr) - 1
# building the max_heap use the function max_heapify
for i in range((arr[0] >> 1), 0, -1):
min_heapify(arr, i)
# test build_min_heap
print("test build_min_heap")
arr = [0, 1, 2, 4, 5, 6]
build_min_heap(arr)
print(arr)
arr = [5, 2, 4, 1, 7, 9, 10]
build_min_heap(arr)
print(arr)
arr = [10, 3, 4, 9, 11, 4, 10]
build_min_heap(arr)
print(arr)
def heap_sort(arr):
'''
Using the heap sort algorithm to sorting a unordered linear array.
Parameters:
arr - the unordered linear array need to sorted
Returns:
the arr[0] recorded the heap-size of the array, orthers recoder value
'''
# using the build_max_heap to build a max_heap
build_max_heap(arr)
# yielding the ith number
for i in range(arr[0], 1, -1):
arr[1], arr[i] = arr[i], arr[1]
arr[0] -= 1
# make sure the arr mantain a max_heap
max_heapify(arr, 1)
# the heap is empty
arr[0] -= 1
# test heap_sort
print("test heap_sort")
arr = [0, 1, 2, 4, 5, 6]
heap_sort(arr)
print(arr)
arr = [5, 2, 4, 1, 7, 9, 10]
heap_sort(arr)
print(arr)
arr = [10, 3, 4, 9, 11, 4, 10]
heap_sort(arr)
print(arr)
def heap_sort_min(arr):
'''
Using the heap sort algorithm to sorting a unordered linear array.This yield
a descent order of the arr
Parameters:
arr - the unordered linear array need to sorted
Returns:
the arr[0] recorded the heap-size of the array, orthers recoder value
'''
# using the build_max_heap to build a max_heap
build_min_heap(arr)
# yielding the ith number
for i in range(arr[0], 1, -1):
arr[1], arr[i] = arr[i], arr[1]
arr[0] -= 1
# make sure the arr mantain a max_heap
min_heapify(arr, 1)
# the heap is empty
arr[0] -= 1
# test heap_sort_min
print("test heap_sort")
arr = [0, 1, 2, 4, 5, 6]
heap_sort_min(arr)
print(arr)
arr = [5, 2, 4, 1, 7, 9, 10]
heap_sort_min(arr)
print(arr)
arr = [10, 3, 4, 9, 11, 4, 10]
heap_sort_min(arr)
print(arr)
# author Ttssxuan
# Chapter 6 6.5
# Use the heap to build a max priority queue
def max_heapify(arr, i):
'''
The list struct as menthioned above.
Maintain the max-heap property use the recursive method. This function
assumes the LEFT(i) and RIGHT(i) are max-heap.
Parameters:
arr - the heap
i - the index input to the array
Returns:
none
'''
pos = i
while True:
# the left children of arr[i]
l = pos << 1
# the right children of arr[i]
r = pos << 1 | 1
#find the largest of the three
if l <= arr[0] and arr[l] > arr[pos]:
largest = l
else:
largest = pos
if r <= arr[0] and arr[r] > arr[largest]:
largest = r
# make the largest of them to the appropriate position
if largest != pos:
arr[pos], arr[largest] = arr[largest], arr[pos]
pos = largest
else:
break
def heap_maximum(arr):
'''
get the maximum of the heap
Parameters:
arr - the heap
Returns:
the maximum of the heap
'''
return arr[1]
def heap_extract_max(arr):
'''
get the max of the priority queue
Parameters:
arr - the priority queue
Returns:
the max of the priority queue
'''
# for sure that the queue is not empty
if arr[0] < 1:
return float('nan')
# get the max of the priority queue
max = arr[1]
# remove the max , and maintain the priority queue
if arr[0] != 1:
arr[1] = arr.pop(arr[0])
else:
arr.pop(1)
arr[0] -= 1
max_heapify(arr, 1)
return max
def heap_increase_key(arr, i, key):
'''
increase the priority of the arr[i] to key
Parameters:
arr - the priority queue
i - the index of element need to increase priority
key - the key assign the arr[i]
Returns:
the priority queue update the key value
'''
if key < arr[i]:
return float('nan')
# assign the new key
arr[i] = key
# maintain the property of the priority queue
while i > 1 and arr[i >> 1] < arr[i]:
# exchange with it's parent
arr[i], arr[i >> 1] = arr[i >> 1], arr[i]
i = i >> 1
def max_heap_insert(arr, key):
'''
insert a new key into the priority queue
Parameters:
arr - the priority queue
key - the new inserting key
Returns:
the new priority queue with the new key
'''
# increase the heap_size
arr[0] += 1
if len(arr) <= arr[0]:
arr.append(0)
arr[arr[0]] = float('-inf')
heap_increase_key(arr, arr[0], key)
import random
# test
# max_heap_insert
arr = [0]
print("test max_heap_insert")
for i in range(10):
max_heap_insert(arr, random.randrange(10))
print(arr)
# heap increase key
print("test heap_increase_key")
for i in range(1, 11):
heap_increase_key(arr, i, arr[i] + 1)
print(arr)
# heap_extract_max
print("test heap_extract_max")
for i in range(1, 11):
print(i, heap_extract_max(arr))
# author Ttssxuan
# Chapter 6 6.5
# Use the heap to build a min priority queue
def min_heapify(arr, i):
'''
The list struct as menthioned above.
Maintain the min-heap property use the recursive method. This function
assumes the LEFT(i) and RIGHT(i) are min-heap.
Parameters:
arr - the heap
i - the index input to the array
Returns:
none
'''
pos = i
while True:
# the left children of arr[i]
l = pos << 1
# the right children of arr[i]
r = pos << 1 | 1
#find the smallest of the three
if l <= arr[0] and arr[l] < arr[pos]:
smallest = l
else:
smallest = pos
if r <= arr[0] and arr[r] < arr[smallest]:
smallest = r
# make the largest of them to the appropriate position
if smallest != pos:
arr[pos], arr[smallest] = arr[smallest], arr[pos]
pos = smallest
else:
break
def heap_minimum(arr):
'''
get the minimum of the heap
Parameters:
arr - the heap
Returns:
the minimum of the heap
'''
return arr[1]
def heap_extract_min(arr):
'''
get the min of the priority queue
Parameters:
arr - the priority queue
Returns:
the min of the priority queue
'''
# for sure that the queue is not empty
if arr[0] < 1:
return float('nan')
# get the min of the priority queue
min = arr[1]
# remove the min, and maintain the priority queue
if arr[0] != 1:
arr[1] = arr[arr[0]]
else:
arr.pop(1)
arr[0] -= 1
min_heapify(arr, 1)
return min
def heap_decrease_key(arr, i, key):
'''
increase the priority of the arr[i] to key
Parameters:
arr - the priority queue
i - the index of element need to decrease priority
key - the key assign the arr[i]
Returns:
the priority queue update the key value
'''
if key > arr[i]:
return float('nan')
# assign the new key
arr[i] = key
# maintain the property of the priority queue
while i > 1 and arr[i >> 1] > arr[i]:
# exchange with it's parent
arr[i], arr[i >> 1] = arr[i >> 1], arr[i]
i = i >> 1
def min_heap_insert(arr, key):
'''
insert a new key into the priority queue
Parameters:
arr - the priority queue
key - the new inserting key
Returns:
the new priority queue with the new key
'''
# increase the heap_size
arr[0] += 1
if len(arr) <= arr[0]:
arr.append(0)
arr[arr[0]] = float('inf')
heap_decrease_key(arr, arr[0], key)
import random
# test
# min_heap_insert
arr = [0]
print("test min_heap_insert")
for i in range(10):
min_heap_insert(arr, random.randrange(10))
print(arr)
# heap decrease key
print("test heap_decrease_key")
for i in range(1, 10):
heap_decrease_key(arr, i, arr[i] - random.randrange(3))
print(arr)
# heap_extract_max
print("test heap_extract_min")
for i in range(1, 10):
print(i, heap_extract_min(arr))
# author Ttss
# 6.5-9
# merge k sorted lists into one sorted list
# the method to implement this is similar to the heap sort, but the heap stored
# the index of the list, when we compare, we compare the conresponed value of
# the index
from math import isnan
def max_heapify(arr, i, lists):
'''
The list struct as menthioned above.
Maintain the max-heap property use the recursive method. This function
assumes the LEFT(i) and RIGHT(i) are max-heap.
Parameters:
arr - the heap
i - the index input to the array
lists - the list array need to merge
Returns:
none
'''
pos = i
while True:
# the left children of arr[i]
l = pos << 1
# the right children of arr[i]
r = pos << 1 | 1
#find the largest of the three, this is judge by the conreponed list
if l <= arr[0] and lists[arr[l]][0] > lists[arr[pos]][0]:
largest = l
else:
largest = pos
if r <= arr[0] and lists[arr[r]][0] > lists[arr[largest]][0]:
largest = r
# make the largest of them to the appropriate position
if largest != pos:
arr[pos], arr[largest] = arr[largest], arr[pos]
pos = largest
else:
break
def heap_extract_max(arr, lists):
'''
get the max of the priority queue
Parameters:
arr - the priority queue
lists - the list array need to merge
Returns:
the max of the priority queue
'''
# for sure that the queue is not empty
if arr[0] < 1:
return float('nan')
# get the max of the priority queue
max = arr[1]
# remove the max , and maintain the priority queue
arr[1] = arr[arr[0]]
arr[0] -= 1
max_heapify(arr, 1, lists)
return max
def heap_increase_key(arr, i, key, lists):
'''
increase the priority of the arr[i] to key
Parameters:
arr - the priority queue
i - the index of element need to increase priority
key - the key assign the arr[i]
lists - the list array need to be merged
Returns:
the priority queue update the key value
'''
if key < arr[i]:
return float('nan')
# assign the new key
arr[i] = key
# maintain the property of the priority queue
while i > 1 and lists[arr[i >> 1]][0] < lists[arr[i]][0]:
# exchange with it's parent
arr[i], arr[i >> 1] = arr[i >> 1], arr[i]
i = i >> 1
def max_heap_insert(arr, key, lists):
'''
insert a new key into the priority queue
Parameters:
arr - the priority queue
key - the new inserting key
lists - the list array need to be merged
Returns:
the new priority queue with the new key
'''
# increase the heap_size
arr[0] += 1
if len(arr) <= arr[0]:
arr.append(0)
arr[arr[0]] = float('-inf')
heap_increase_key(arr, arr[0], key, lists)
def merge_lists(*lists):
'''
calculate the list array merge to a single list
Parameters:
lists - the list array need to be merged
Returns:
the merged list
'''
# get the number of the lists
lists_len = len(lists)
# init the heap
arr = [0]
# init the result
result = []
# construct a heap first
for i in range(lists_len):
max_heap_insert(arr, i, lists)
# get the max in the heap
re = heap_extract_max(arr, lists)
while not isnan(re):
# get the result
result.append(lists[re].pop(0))
# judge whether the lists[re] had been merged
if len(lists[re]) > 0:
max_heap_insert(arr, re, lists)
re = heap_extract_max(arr, lists)
return result
# test
arr1 = [100, 2, -1]
arr2 = [4, 3, 2]
arr3 = [20, 5, -1, -10]
print(merge_lists(arr1, arr2, arr3))
# author Ttssxuan
# 6-2
# analysis of d-ary heaps
from math import floor
def parent(i, d):
'''
get the parent of d, in the d-ary heap
Parameters:
i - the index of current node
d - the array of the heap
Returns:
the parent index of the i node
'''
return int(floor((i - 2) / d)) + 1
def child(i, j, d):
'''
get the jth child of i in the d-ary heap
Parameters:
i - the index of current node
j - the order of the child, j begins in 0
d - the array of the heap
Returns:
the index of the jth child of the i node
'''
return d * (i - 1) + j + 2
def max_heapify(arr, i, d):
'''
the arr[0] stored the heap-size and the value start at arr[1]
make the arr[i] adapt the d-ary heap property, this is assum that the
children of arr[i] are the root of the d-ary heap
Parameters:
arr - the heap
'''
pos = i
while True:
largest = pos
# find the largest one among the arr[pos] and it's children
for j in range(0, d):
temp = child(pos, j, d)
if temp <= arr[0]:
if arr[temp] > arr[largest]:
largest = temp
else:
break
# move the largest to property position and maintain the d-ary heap
# property
if largest != pos:
arr[pos], arr[largest] = arr[largest], arr[pos]
pos = largest
else:
break
def heap_extract_max(arr, d):
'''
get the max from the d-ary heap
Parameters:
arr - the d-ary heap
d - the array of the heap
Returns:
the max value of the d-ary heap, if error return nan
'''
# for sure taht the queue is not empty
if arr[0] < 1:
return float('nan')
# get the max of the d-ary heap
max = arr[1]
# remove the max of the d-ary heap
if arr[0] != 1:
arr[1] = arr.pop(arr[0])
else:
arr.pop(1)
arr[0] -= 1
max_heapify(arr, 1, d)
return max
def heap_increase_key(arr, i, key, d):
'''
increase the value of arr[i] and maintain the d-ary heap
Parameters:
arr - the d-ary heap
i - the index of the element need to increase
d - the array of heap
Return:
the increased arr, if error retrun nan
'''
if key < arr[i]:
return float('nan')
# assign the new key
arr[i] = key
# maintain the properties of the d-ary heap
while i > 1 and arr[parent(i, d)] < arr[i]:
arr[i], arr[parent(i, d)] = arr[parent(i, d)], arr[i]
i = parent(i, d)
def max_heap_insert(arr, key, d):
'''
insert a new key into the d-ary queue
'''
# increase the heap_size
arr[0] += 1
if len(arr) <= arr[0]:
arr.append(0)
arr[arr[0]] = float('-inf')
heap_increase_key(arr, arr[0], key, d)
import random
# test
# max_heap_insert
arr = [0]
d = 3
print("test max_heap_insert")
for i in range(10):
max_heap_insert(arr, random.randrange(10), d)
print(arr)
# heap increase key
print("test heap_increase_key")
for i in range(1, 11):
heap_increase_key(arr, i, arr[i] + 1, d)
print(arr)
# heap_extract_max
print("test heap_extract_max")
for i in range(1, 11):
print(i, heap_extract_max(arr, d), arr)
# author Ttssxuan
# 6-3 c
# the algorithm extract-min on a noempty m*n Young tableaus
def min_tableaus(arr, m, n, init_x, init_y):
'''
rearrange the matrix and makes if fulfill the property of young tableaus
assume others fulfill the property, except this one
Parameters:
arr - the young tableaus
m - the number of rows of the matrix
n - the number of columns of the matrix
'''
pos_x = init_x
pos_y = init_y
while True:
bottom_x = pos_x + 1
right_y = pos_y + 1
# find the smallest of the three
if bottom_x < m and arr[bottom_x][pos_y] < arr[pos_x][pos_y]:
smallest_x = bottom_x
smallest_y = pos_y
else:
smallest_x = pos_x
smallest_y = pos_y
if right_y < n and arr[pos_x][right_y] < arr[smallest_x][smallest_y]:
smallest_x = pos_x
smallest_y = right_y
# move the value to the appropriate place
if smallest_x != pos_x or smallest_y != pos_y:
arr[pos_x][pos_y], arr[smallest_x][smallest_y] = arr[smallest_x][smallest_y], arr[pos_x][pos_y]
pos_x = smallest_x
pos_y = smallest_y
else:
break
def extract_min(arr, m, n):
'''
get the minimum of the young tableaus and maintain the property
Parameters:
arr - the young tableaus
m - the number of young tableaus rows
n - the number of young tableaus columns
Returns:
the young tableaus extracted the minimum value
'''
if n <= 0 or m <= 0:
return float('nan')
# extract the minimum
min = arr[0][0]
arr[0][0] = float('inf')
# rearrange the young tableaus
min_tableaus(arr, m, n, 0, 0)
return min
def insert(arr, m, n, key):
pos_x = m - 1
pos_y = n - 1
arr[pos_x][pos_y] = key
while True:
top_x = pos_x - 1
left_y = pos_y - 1
# find the smallest of the three
if top_x >= 0 and arr[top_x][pos_y] > arr[pos_x][pos_y]:
largest_x = top_x
largest_y = pos_y
else:
largest_x = pos_x
largest_y = pos_y
if left_y >= 0 and arr[pos_x][left_y] > arr[largest_x][largest_y]:
largest_x = pos_x
largest_y = left_y
# move the value to the appropriate place
if largest_x != pos_x or largest_y != pos_y:
arr[pos_x][pos_y], arr[largest_x][largest_y] = arr[largest_x][largest_y], arr[pos_x][pos_y]
pos_x = largest_x
pos_y = largest_y
else:
break
def contain(arr, m, n, value, x, y):
'''
verify the arr[x][y] == value, otherwise adjust the range of search
Parameters:
arr - the tableaus
m - the number of tableaus rows
n - the number of tableaus columns
x - the new x range
y - the new y range
Returns:
if find the value return it't position, or return -1, -1
'''
if x >= m or y < 0:
return -1, -1
if arr[x][y] == value:
return x, y
xx = x
yy = y
# adjustment the range of search
if arr[x][y] < value:
xx += 1
if arr[x][y] > value:
yy -= 1
return contain(arr, m, n,value, xx, yy)
def find(arr, m, n, value):
'''
verify if the value exist in the tableaus
Parameters:
arr - the young tableaus
m - the number of the tableaus rows
n - the number of the tableaus columns
Returns:
if find the value return the conresponde position, otherwise return
-1 -1
'''
return contain(arr, m, n, value, 0, n - 1)
# test
import random
row = random.randrange(4, 6)
column = random.randrange(2, 5)
arr = [[float('inf') for x in range(column)] for y in range(row)]
# test insert
for i in range(column * row):
insert(arr, row, column, random.randrange(10))
print(i, arr)
print(arr)
# test find
print("find 5", find(arr, row, column, 5))
print("find 7", find(arr, row, column, 7))
print("find 1", find(arr, row, column, 1))
print("find 4", find(arr, row, column, 4))
print("find 10", find(arr, row, column, 10))
# test extract_min
for i in range(column * row):
print(extract_min(arr, row, column), arr)