diff --git a/heapsort.py b/heapsort.py new file mode 100644 index 0000000..e4a4fc9 --- /dev/null +++ b/heapsort.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 + +import sys + +def heap_extract_max(A): + m = A[0] + A[0] = A.pop() + + size = len(A) + i = 0 + exit = size == 0 + while exit: + left = heap_left(i) + if left == None: + break + + right = heap_right(i) + if right == None: + if A[i] < A[left]: + A[i], A[left] = A[left], A[i] + break + + ma = max_3(A[i], A[left], A[right]) + if ma == A[i]: + break + elif ma == A[left]: + A[i], A[left] = A[left], A[i] + i = left + else: + A[i], A[right] = A[right], A[i] + i = right + + return m + +def max_3(a, b, c): + if a > b: + if a > c: + return a + else: + return c + else: + if b > c: + return b + else: + return c + +def heap_parent(n): + n = n + 1 + if n == 1: + return None + else + return (n // 2) - 1 + +def heap_left(size, n): + n = n + 1 + l = n * 2 + if l > size + return None + else + return l - 1 + +def heap_right(size, n): + n = n + 1 + l = n * 2 + 1 + if l > size + return None + else + return l - 1 + +if __name__ == "__main__": + args = [int(x) for x in sys.argv[1:]] + diff --git a/notes.md b/notes.md index 65667a9..402579a 100644 --- a/notes.md +++ b/notes.md @@ -99,3 +99,47 @@ stated. The algorithm must terminate. Invariant condition able to make a loop equivalent to a straight path in an execution graph. + +# Heaps and Heapsort + +A data structure is a way to structure data. +A binary heap is like an array and can be of two types: max heap and min heap. + +## Interface of an heap +- `Build_max_heap(A)` and rearranges a into a max-heap; +- `Heap_insert(H, key)` inserts `key` in the heap; +- `Heap_extract_max(H)` extracts the maximum `key`; +- `H.heap_size` returns the size of the heap. + +A binary heap is like a binary tree mapped on an array: + +``` + 1 + / \ + / \ + 2 3 +/ \ / \ +4 5 6 7 + +=> [1234567] +``` + +The parent position of `n` is the integer division of n by 2: + +```python +def parent(x): + return x // 2 +``` + +The left of `n` is `n` times 2, and the right is `n` times 2 plus 1: + +```python +def left(x): + return x * 2 + +def right(x): + return x * 2 + 1 +``` + +**Max heap property**: for all i > 1 A[parent(i)] >= A[i] + diff --git a/partition.py b/partition.py new file mode 100644 index 0000000..039f4c4 --- /dev/null +++ b/partition.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 + +import sys +import random + +def partition(A, begin, end): + v_i = random.randrange(begin, end) + v = A[v_i] + A[v_i], A[end-1] = A[end-1], A[v_i] + i = begin + j = end - 2 + while j >= i: + if A[j] > v: + j = j - 1 + elif A[i] <= v: + i = i + 1 + else: + A[i], A[j] = A[j], A[i] + j = j - 1 + i = i + 1 + A[i], A[end-1] = A[end-1], A[i] + return i + +def quicksort(A, begin, end): + if begin < end - 1: + i = partition(A, begin, end) + print(A[begin:i], A[i], A[i+1:end]) + quicksort(A, begin, i) + quicksort(A, i+1, end) + print(A[begin:i], A[i], A[i+1:end]) + +if __name__ == "__main__": + args = [int(x) for x in sys.argv[1:]] + print(args) + quicksort(args, 0, len(args)) + print(args) +