diff --git a/notes.md b/notes.md index 6a579f0..03a707f 100644 --- a/notes.md +++ b/notes.md @@ -246,15 +246,13 @@ insertion and search. ## Growing a *chained hash table* -In order to grow a table, a new table must be created. The hash function (or it -s -range parameters) must be changed as well. +In order to grow a table, a new table must be created. The hash function (or +its range parameters) must be changed as well. ### Rehashing *Rehashing* is the process of putting all the elements of the old table in the -new -table according to the new hash function. The complexity is O(n), since +new table according to the new hash function. The complexity is O(n), since `Chained-hash-insert` is constant. ### Growing the table every time @@ -279,4 +277,40 @@ that has ...) - `Tree-Search(T, k)` returns if key K is in the tree T; - `Tree-Minimum(T)` finds the smallest element in the tree; - `Tree-Maximum(T)` finds the biggest element in the tree; -- `Tree-successor(T, k)` `Tree-predecessor(T, k) +- `Tree-successor(T, k)` and `Tree-predecessor(T, k)` find the next and + previous position in the tree + +## Height of a tree + +The height of a tree is the maximum number of edges traversed from parent to +child in order to reach a leaf from the root of the tree. + +## Rotation + +``` + b + / \ + a \ + / \ \ + / \ \ +k <= a a <= k <= b k >= b +``` + +``` + a + / \ + / b + / / \ + / / \ +k <= a a <= k <= b k >= b +``` + +# Red-Black trees + +1. Every node has a color: red or black +2. The root is black +3. Every NULL leaf node is black +4. If a node is red, both of its children are black +5. The black height is the same for every branch in the tree + +A red node is a way to strech the tree, but the diff --git a/partition.py b/partition.py index 039f4c4..c455ffa 100755 --- a/partition.py +++ b/partition.py @@ -1,37 +1,40 @@ #!/usr/bin/env python3 +# vim: set ts=2 sw=2 et tw=80: 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 + 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 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) - + args = [int(x) for x in sys.argv[1:]] + print(args) + quicksort(args, 0, len(args)) + print(args) diff --git a/tree.py b/tree.py index eb849d5..b2fabfa 100644 --- a/tree.py +++ b/tree.py @@ -1,10 +1,210 @@ #!/usr/bin/env python3 # vim: set ts=2 sw=2 et tw=80: +import sys + + class Node: def __init__(self, k): self.key = k self.left = None self.right = None + self.parent = None + + def set_left(self, kNode): + kNode.parent = self + self.left = kNode + + def set_right(self, kNode): + kNode.parent = self + self.right = kNode +tree = Node(77) +tree.set_left(Node(30)) +tree.left.set_left(Node(21)) +tree.left.set_right(Node(33)) +tree.left.right.set_left(Node(31)) +tree.left.right.set_right(Node(50)) +tree.set_right(Node(78)) +tree.right.set_right(Node(80)) + + +# Complexity: Theta(n) +def in_order_walk(t): + if t is not None: + in_order_walk(t.left) + print(t.key, end=' ') + in_order_walk(t.right) + + +# Complexity: Theta(n) +def reverse_walk(t): + if t is not None: + reverse_walk(t.right) + print(t.key, end=' ') + reverse_walk(t.left) + + +# Complexity (worst): Theta(n) +def search(tree, k): + pass + + +# Complexity (worst): Theta(n) +def min(t): + if t is None: + return None + while t.left is not None: + t = t.left + return t + + +# Complexity (worst): Theta(n) +def max(t): + if t is None: + return None + while t.right is not None: + t = t.right + return t + + +def successor(t): + if t.right is not None: + return min(t.right) + while t.parent is not None: + if t.parent.left == t: + return t.parent + else: + t = t.parent + return None + + +def predecessor(t): + if t.left is not None: + return max(t.left) + while t is not None: + if t.parent.right == t: + return t.parent + else: + t = t.parent + return None + + +def insert(t, k): + if t is None: + return Node(k) + if t.key < t.key: + t.set_left(insert(t.left, k)) + else: + tree.set_right(insert(t.right, k)) + return t + +def right_rotate(x): + # assume x is not None + # assume x.left is not None + t = x.left + x.left = t.right + t.right = x + return t + +def left_rotate(x): + # assume x is not None + # assume x.right is not None + t = x.right + x.right = t.left + t.left = x + return t + +def root_insert(t, k): + if t is None: + return Node(k) + if k > t.key: + t.set_right(root_insert(t.right, k)) + return left_rotate(t) + else: + t.set_left(root_insert(t.left, k)) + return right_rotate(t) + +############################################################################### +# Code for printing trees, ignore this + + +class Canvas: + def __init__(self, width): + self.line_width = width + self.canvas = [] + + def put_char(self, x, y, c): + if x < self.line_width: + pos = y * self.line_width + x + l = len(self.canvas) + if pos < l: + self.canvas[pos] = c + else: + self.canvas[l:] = [' '] * (pos - l) + self.canvas.append(c) + + def print_out(self): + i = 0 + for c in self.canvas: + sys.stdout.write(c) + i = i + 1 + if i % self.line_width == 0: + sys.stdout.write('\n') + if i % self.line_width != 0: + sys.stdout.write('\n') + + +def print_binary_r(t, x, y, canvas): + max_y = y + if t.left is not None: + x, max_y, lx, rx = print_binary_r(t.left, x, y + 2, canvas) + x = x + 1 + for i in range(rx, x): + canvas.put_char(i, y + 1, '/') + + middle_l = x + for c in str(t.key): + canvas.put_char(x, y, c) + x = x + 1 + middle_r = x + + if t.right is not None: + canvas.put_char(x, y + 1, '\\') + x = x + 1 + x0, max_y2, lx, rx = print_binary_r(t.right, x, y + 2, canvas) + if max_y2 > max_y: + max_y = max_y2 + for i in range(x, lx): + canvas.put_char(i, y + 1, '\\') + x = x0 + + return (x, max_y, middle_l, middle_r) + + +def print_tree(t): + print_w(t, 80) + + +def print_w(t, width): + canvas = Canvas(width) + print_binary_r(t, 0, 0, canvas) + canvas.print_out() + +############################################################################### + + +if __name__ == "__main__": + print_tree(tree) + + in_order_walk(tree) + print() + + reverse_walk(tree) + print() + + print(tree.left.right.right.key) + print(successor(tree.left.right.right).key) + print(predecessor(tree.left.right.right).key) +