Add new course

This commit is contained in:
AndrewTrieu
2023-01-08 18:43:01 +02:00
parent 75313f3f05
commit 6f5c7f67b4
49 changed files with 835669 additions and 0 deletions

View File

@@ -0,0 +1,128 @@
class AVLNode:
# Constructor for new node
def __init__(self, key: int):
self.key = key
self.left = None
self.right = None
self.balance = 0
class AVL:
# Constructor for new AVL
def __init__(self):
self.root = None
self.is_balanced = True
# Inserts a new key to the search tree
def insert(self, key):
self.root = self.insert_help(self.root, key)
# Help function for insert
def insert_help(self, root, key):
if not root:
root = AVLNode(key)
self.is_balanced = False
elif key < root.key:
root.left = self.insert_help(root.left, key)
if not self.is_balanced: # Check for possible rotations
if root.balance >= 0: # No Rotations needed, update balance variables
self.is_balanced = root.balance == 1
root.balance -= 1
# Rotation(s) needed
else:
if root.left.balance == -1:
root = self.right_rotation(root) # Single rotation
else:
root = self.left_right_rotation(
root) # Double rotation
self.is_balanced = True
elif key > root.key:
root.right = self.insert_help(root.right, key)
if not self.is_balanced: # Check for possible rotations
if root.balance <= 0: # No Rotations needed, update balance variables
self.is_balanced = root.balance == -1
root.balance += 1
# Rotation(s) needed
else:
if root.right.balance == 1:
root = self.left_rotation(root)
else:
root = self.right_left_rotation(root)
self.is_balanced = True
return root
# Single rotation: right rotation around root
def right_rotation(self, root):
child = root.left # Set variable for child node
root.left = child.right # Rotate
child.right = root
child.balance = root.balance = 0 # Fix balance variables
return child
# Single rotation: left rotation around root
def left_rotation(self, root):
child = root.right # Set variable for child node
root.right = child.left # Rotate
child.left = root
child.balance = root.balance = 0 # Fix balance variables
return child
# Double rotation: left rotation around child node followed by right rotation around root
def left_right_rotation(self, root):
child = root.left
# Set variables for child node and grandchild node
grandchild = child.right
child.right = grandchild.left # Rotate
grandchild.left = child
root.left = grandchild.right
grandchild.right = root
root.balance = child.balance = 0 # Fix balance variables
if grandchild.balance == -1:
root.balance = 1
elif grandchild.balance == 1:
child.balance = -1
grandchild.balance = 0
return grandchild
# Double rotation: right rotation around child node followed by left rotation around root
def right_left_rotation(self, root):
child = root.right
# Set variables for child node and grandchild node
grandchild = child.left
child.left = grandchild.right # Rotate
grandchild.right = child
root.right = grandchild.left
grandchild.left = root
root.balance = child.balance = 0 # Fix balance variables
if grandchild.balance == 1:
root.balance = -1
elif grandchild.balance == -1:
child.balance = 1
grandchild.balance = 0
return grandchild
def preorder(self):
print(self.preorder_help(self.root))
def preorder_help(self, root):
if not root:
return ''
return str(root.key) + ';' + str(root.balance) + ' ' + self.preorder_help(root.left) + self.preorder_help(root.right)
# Returns the height of the tree
def height(self):
return self.height_help(self.root)
def height_help(self, root):
if not root:
return 0
return 1 + max(self.height_help(root.left), self.height_help(root.right))
if __name__ == "__main__":
# Make a list from 5 19 3 9 4 16 13 8 14 11 7 17 2 15 1 10 6 12 20 18
Tree = AVL()
for key in [5, 19, 3, 9, 4, 16, 13, 8, 14, 11, 7, 17, 2, 15, 1, 10, 6, 12, 20, 18]:
Tree.insert(key)
Tree.preorder()

View File

@@ -0,0 +1,172 @@
<!doctype html>
<html>
<head>
<title>Week 6 Programming Assignments (8 points)</title>
<meta charset="utf-8">
</head>
<body>
<div>
<h4><strong>Assignment 6.1: The AVL Tree</strong><span>&nbsp;(5 points)</span></h4>
</div>
<div>The following Python code implements the AVL tree which can do single and double rotations to the right. Finalize the class <strong>AVL</strong> by creating following methods:</div>
<ul>
<ul>
<li><strong>left_rotation(root: AVLNode)</strong>: symmetrical to
<strong>right_rotation</strong>
</li>
<li><strong>right_left_rotation(root: AVLNode)</strong>: symmetrical to <strong>left_right_rotation</strong></li>
<li><strong>preorder()</strong>: enumerates the keys and their balance values in preorder</li>
<ul>
<li>the format: 'key1:balance1 key2:balance2 key3:balance3'</li>
</ul>
</ul>
</ul>
<div>Finally, finalize the method <strong>insert_help</strong> so that it functions properly.</div>
<p></p>
<div><span>
<div>Submit your solution in CodeGrade as <strong>AVL.py</strong>.</div>
</span><br></div>
<div>An example program: </div>
<p></p>
<div style="border:2px solid black">
<pre>if __name__ == "__main__":
Tree = AVL()
for key in [9, 10, 11, 3, 2, 6, 4, 7, 5, 1]:
Tree.insert(key)
Tree.preorder() # 9;-1 4;0 2;0 1;0 3;0 6;0 5;0 7;0 10;1 11;0
</pre>
</div>
<div><br></div>
<div>A code template for the AVL tree: </div>
<p></p>
<div style="border:2px solid black">
<pre>class AVLNode:
# Constructor for new node
def __init__(self, key: int):
self.key = key
self.left = None
self.right = None
self.balance = 0
class AVL:
# Constructor for new AVL
def __init__(self):
self.root = None
self.is_balanced = True
# Inserts a new key to the search tree
def insert(self, key):
self.root = self.insert_help(self.root, key)
# Help function for insert
def insert_help(self, root, key):
if not root:
root = AVLNode(key)
self.is_balanced = False
elif key &lt; root.key:
root.left = self.insert_help(root.left, key)
if not self.is_balanced: # Check for possible rotations
if root.balance &gt;= 0: # No Rotations needed, update balance variables
self.is_balanced = root.balance == 1
root.balance -= 1
else: # Rotation(s) needed
if root.left.balance == -1:
root = self.right_rotation(root) # Single rotation
else:
root = self.left_right_rotation(root) # Double rotation
self.is_balanced = True
elif key &gt; root.key:
root.right = self.insert_help(root.right, key)
# TODO
return root
# Single rotation: right rotation around root
def right_rotation(self, root):
child = root.left # Set variable for child node
root.left = child.right # Rotate
child.right = root
child.balance = root.balance = 0 # Fix balance variables
return child
# Single rotation: left rotation around root
def left_rotation(self, root):
# TODO
# Double rotation: left rotation around child node followed by right rotation around root
def left_right_rotation(self, root):
child = root.left
grandchild = child.right # Set variables for child node and grandchild node
child.right = grandchild.left # Rotate
grandchild.left = child
root.left = grandchild.right
grandchild.right = root
root.balance = child.balance = 0 # Fix balance variables
if grandchild.balance == -1:
root.balance = 1
elif grandchild.balance == 1:
child.balance = -1
grandchild.balance = 0
return grandchild
# Double rotation: right rotation around child node followed by left rotation around root
def right_left_rotation(self, root):
# TODO
</pre>
</div>
<br>
<br>
<div>
<h4><strong>Assignment 6.2: The Min Heap</strong>&nbsp;(3 points)</h4>
</div>
<div>Implement the min heap structure that stores positive integers in Python. Create class <strong>MinHeap</strong> which has following functions:</div>
<ul>
<ul>
<li><strong>push(key: int)</strong>: inserts a new key to the heap while maintaining the min heap property.<br></li>
<li><strong>pop(): </strong>removes the smallest key from the heap and returns its value. </li>
<li><strong>print()</strong>: prints the heap in breadth-first order<ul>
<li>the format: key values separated by spaces (e.g. 1 2 3 4).<br></li>
</ul>
</li>
</ul>
</ul>
<div>Make sure that the heap always maintains the min heap property. The best practice is to store the heap structure in a list where a key in index \(i\)</div>
<ul>
<ul>
<li>has a left child at index \(2i + 1\)</li>
<li>has a right child at index \(2i + 2\)</li>
<li>has its parent at index \(\lfloor \frac{i-1}{2} \rfloor\) (\(\lfloor \ldots \rfloor\) rounds down to the nearest integer)<br></li>
</ul>
</ul>
<div>A code template an example program: </div>
<p></p>
<div style="border:2px solid black">
<pre>class MinHeap:
# TODO
if __name__ == "__main__":
items = [4, 8, 6, 5, 1, 2, 3]
heap = MinHeap()
[heap.push(key) for key in items]
heap.print() # 1 4 2 8 5 6 3
print(heap.pop()) # 1
heap.print() # 2 4 3 8 5 6
</pre>
</div>
<p></p>
<div>Submit your solution in CodeGrade as <strong>minheap.py</strong>.</div>
</body>
</html>

View File

@@ -0,0 +1,49 @@
class MinHeap:
def __init__(self):
self.heap = []
def push(self, key):
self.heap.append(key)
self.bubble_up(len(self.heap) - 1)
def bubble_up(self, index):
if index == 0:
return
parent = (index - 1) // 2
if self.heap[parent] > self.heap[index]:
self.heap[parent], self.heap[index] = self.heap[index], self.heap[parent]
self.bubble_up(parent)
def pop(self):
if len(self.heap) == 0:
return None
if len(self.heap) == 1:
return self.heap.pop()
self.heap[0], self.heap[-1] = self.heap[-1], self.heap[0]
min = self.heap.pop()
self.bubble_down(0)
return min
def bubble_down(self, index):
left = 2 * index + 1
right = 2 * index + 2
smallest = index
if left < len(self.heap) and self.heap[left] < self.heap[smallest]:
smallest = left
if right < len(self.heap) and self.heap[right] < self.heap[smallest]:
smallest = right
if smallest != index:
self.heap[smallest], self.heap[index] = self.heap[index], self.heap[smallest]
self.bubble_down(smallest)
def print(self):
print(' '.join(map(str, self.heap)))
if __name__ == "__main__":
items = [4, 8, 6, 5, 1, 2, 3]
heap = MinHeap()
[heap.push(key) for key in items]
heap.print() # 1 4 2 8 5 6 3
print(heap.pop()) # 1
heap.print() # 2 4 3 8 5 6