forked from iiitv/algos
-
Notifications
You must be signed in to change notification settings - Fork 5
/
heap_sort.py
128 lines (99 loc) · 3.28 KB
/
heap_sort.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
"""
Following is the implementation of heap_sort algorithm.
It will sort the input array with time complexity O(N*logN)
N being the size of array.
Space complexity is O(1).
"""
def left_child_index(i):
"""
:param i: int
Index of node in array (that is organized as heap)
:return: int
Position in array of left child of node
"""
return 2 * (i + 1) - 1
def right_child_index(i):
"""
:param i: int
Index of node in array (that is organized as heap)
:return: int
Position in array of right child of node
"""
return left_child_index(i) + 1
def get_children_of_node(a, i):
"""
:param a: list
List organized as heap, i.e for each node i:
left children is at position 2(i + 1) - 1
right children is at position 2(i + 1))
:param i: int
Index of parent node in array (that is organized as heap)
:return: (left children index, left children node) and
(right children index, right children node)
"""
l = left_child_index(i) # index and value of children
l_val = a[l] if 0 <= l < len(a) else None
r = right_child_index(i)
r_val = a[r] if 0 <= r < len(a) else None
return (l, l_val), (r, r_val)
def find_largest_in_family(a, i):
"""
:param a: list
List organized as heap, i.e for each node i:
left children is at position 2(i + 1) - 1
right children is at position 2(i + 1))
:param i: int
Index of parent node in array (that is organized as heap)
:return: index of largest value among parent and children
"""
(l, l_val), (r, r_val) = get_children_of_node(a, i)
largest_i = i # find index of largest value among a[i] and its children
if l_val is not None and l_val > a[i]:
largest_i = l
if r_val is not None and r_val > a[largest_i]:
largest_i = r
return largest_i
def max_heapify(a, i):
"""
:param a: list
List organized as heap, i.e for each node i:
left children is at position 2(i + 1) - 1
right children is at position 2(i + 1))
:param i: int
Index of array where to start checking for max-heap condition from
:return: list
List organized as max-heap.
"""
largest_i = find_largest_in_family(a, i) # find largest node
if largest_i != i: # swap only if it's needed
a[largest_i], a[i] = a[i], a[largest_i] # swap
return max_heapify(a, largest_i)
return a
def heap_sort(a):
"""
:param a: list
List of objects with an order
:return: list
Sorted list with heap sort algorithm
"""
for i in range(len(a) // 2, 0, -1):
a = max_heapify(a, i) # create max-heap
for i in range(len(a) // 2, 0, -1):
a[0], a[i] = a[i], a[0] # swap first and last item
a = max_heapify(a, i)
return a
def main():
"""
:return: void
Sorts sample list with heap sort algorithm,
then prints sorted list
"""
unsorted_list = [
437230, 851821, 184681, 173673, 13306, 768361, 431982, 956700, 65143,
556681, 198208, 983511, 170469, 313978, 552536, 334818, 527289,
959491, 303675, 532988
]
sorted_list = heap_sort(unsorted_list)
print(sorted_list)
if __name__ == '__main__':
main()