Midterm Note
Midterm Note
• Must-have import
from typing import List, Tuple, Callable, Union, Optional
from time import time
import numpy as np
• Bubble Sort
def BubbleSort(array: Union[List, Tuple, np.ndarray], reverse: bool = False):
# Implementation of Bubble Sort from Right to Left
for x in range(0, len(array):
swapped = False
for y in range(len(array) – 1, x, -1):
if array[y - 1] > array[y]:
array[y - 1], array[y], swapped = array[y], array[y - 1], True
if swapped is False:
break
# Implementation of Bubble Sort from Left to Right
swap: bool = True
num_iter: int = 0
while swap is True:
swap = False
for x in range(0, len(arr) - num_iter - 1):
if arr[x] > arr[x + 1]:
arr[x], arr[x + 1] = arr[x + 1], arr[x]
swap = True
num_iter += 1
• Selection Sort
def SelectionSort(array, reverse: bool = False):
def search(arr, search_maximum: bool = False):
index = 0
if search_maximum is False:
for i in range(1, len(arr)):
if arr[i] < arr[index]:
index = i
else:
for i in range(1, len(arr)):
if arr[i] > arr[index]:
index = i
return index
if reverse is False:
for current_index in range(0, len(array)):
index = current_index + search(arr=array[current_index:], search_maximum=False)
if index != current_index:
array[current_index], array[index] = array[index], array[current_index]
else:
for current_index in range(0, len(array)):
index = current_index + search(arr=array[current_index:], search_maximum=True)
if index != current_index:
array[current_index], array[index] = array[index], array[current_index]
• Insertion Sort
def InsertionSort(arr, reverse: bool = False):
if reverse is False:
for index in range(1, len(array)):
if array[index - 1] < array[index]:
continue
for i in range(0, index):
if array[i] > array[index]:
key = array[index]
array[i + 1: index + 1] = array[i:index]
array[i] = key
break
else:
for index in range(1, len(array)):
if array[index - 1] > array[index]:
continue
for i in range(0, index):
if array[i] < array[index]:
key = array[index]
array[i + 1: index + 1] = array[i:index]
array[i] = key
break
if reverse is False:
if start == end:
if array[start] > value:
return start
else:
return start + 1
else:
if start == end:
if array[start] < value:
return start
else:
return start + 1
class LL:
def __init__(self, dtype):
if dtype == "LL":
return LinkedList()
elif dtype == "CLL":
return CircularLinkedList()
elif dtype == "DLL":
return DoubleLinkedList()
elif dtype == "DCLL":
return DoubleCircularLinkedList()
else:
raise ValueError("False Value")
def display(self):
return self.build_array(verbose=True)
def display_status(self):
pass
class LinkedList:
def __init__(self):
self.head = None
self.num_of_node = 0
node = Node(value=value)
if self.head is not None:
node.next = self.head
self.head = node
self.num_of_node += 1
if self.head is None:
self.insertFirst(value=value)
else:
node = Node(value=value)
current_node = self.head
while current_node.next is not None:
current_node = current_node.next
current_node.next = node
self.num_of_node += 1
current_node = self.head
for value in valueArray:
current_node.value = value
current_node = current_node.next
stack = []
current_node = self.head
while current_node.next is not None:
if verbose is True:
print(current_node.value, end=" ")
stack.append(current_node.value)
current_node = current_node.next
stack.append(current_node.value)
if verbose is True:
print(current_node.value, end="\n")
return stack
def display(self):
return self.build_array(verbose=True)
def display_status(self):
current_node = self.head
while current_node.next is not None:
print(current_node.value, current_node.next)
current_node = current_node.next
print(current_node.value, current_node.next)
class CircularLinkedList:
def __init__(self):
self.head = None
self.num_of_node = 0
self.last_node: Node = None
node = Node(value=value)
if self.head is None:
self.head = node
self.head.next = self.head
self.last_node = node
else:
self.last_node.next = node
node.next = self.head
if insert_at_begin is True:
self.head = node
else:
self.last_node = node
self.num_of_node += 1
def insertFirst(self, value: Union[int, float]):
self.insert(value=value, insert_at_begin=True)
current_node = self.head
for value in valueArray:
current_node.value = value
current_node = current_node.next
stack = []
current_node = self.head
while current_node.next != self.head:
if verbose is True:
print(current_node.value, end=" ")
stack.append(current_node.value)
current_node = current_node.next
stack.append(current_node.value)
if verbose is True:
print(current_node.value, end="\n")
if len(stack) != self.num_of_node:
warning(" Something is wrong with the number of values in Linked List")
return stack
def display(self):
return self.build_array(verbose=True)
def display_status(self):
current_node = self.head
while current_node.next != self.head:
print(current_node.value, current_node.next)
current_node = current_node.next
print(current_node.value, current_node.next)
class DoubleLinkedList:
def __init__(self):
self.head = None
self.num_of_node = 0
if self.head is None:
self.head = Node(value=value)
else:
node = Node(value=value)
self.head.prev = node
node.next = self.head
self.head = node
self.num_of_node += 1
if self.head is None:
self.insertFirst(value=value)
else:
node = Node(value=value)
current_node = self.head
while current_node.next is not None:
current_node = current_node.next
current_node.next = node
node.prev = current_node
self.num_of_node += 1
current_node = self.head
for value in valueArray:
current_node.value = value
current_node = current_node.next
stack = []
current_node = self.head
while current_node.next is not None:
if verbose is True:
print(current_node.value, end=" ")
stack.append(current_node.value)
current_node = current_node.next
stack.append(current_node.value)
if verbose is True:
print(current_node.value, end="\n")
return stack
def display(self):
return self.build_array(verbose=True)
def display_status(self):
current_node = self.head
while current_node.next is not None:
print("{}, next: {}, prev: {}".format(current_node.value, current_node.next, current_node.prev))
current_node = current_node.next
print("{}, next: {}, prev: {}".format(current_node.value, current_node.next, current_node.prev))
class DoubleCircularLinkedList:
def __init__(self):
self.head = None
self.num_of_node = 0
node = Node(value=value)
if self.head is None:
self.head = node
self.head.next = self.head
self.head.prev = self.head.next
else:
last_node = self.head.prev
last_node.next = node
node.prev = last_node
node.next = self.head
self.head.prev = node
if insert_at_begin is True:
self.head = node
self.num_of_node += 1
current_node = self.head
for value in valueArray:
current_node.value = value
current_node = current_node.next
def delete(self, value: Union[int, float], delete_all: bool = False):
if not isinstance(value, (int, float)):
warning(" Your value is not fit")
stack = []
current_node = self.head
while current_node.next != self.head:
if verbose is True:
print(current_node.value, end=" ")
stack.append(current_node.value)
current_node = current_node.next
stack.append(current_node.value)
if verbose is True:
print(current_node.value, end="\n")
if len(stack) != self.num_of_node:
warning(" Something is wrong with the number of values in Linked List")
return stack
def display(self):
return self.build_array(verbose=True)
def display_status(self):
current_node = self.head
while current_node.next != self.head:
print("{}, next: {}, prev: {}".format(current_node.value, current_node.next, current_node.prev))
current_node = current_node.next
print("{}, next: {}, prev: {}".format(current_node.value, current_node.next, current_node.prev))
Test Case:
if __name__ == '__main__':
LL = DoubleCircularLinkedList()
LL.insertFirst(value=100)
LL.insertFirst(value=200)
LL.insertFirst(value=5000)
LL.insertFirst(value=1000)
LL.insertFirst(value=2000)
LL.insertFirst(value=7000)
LL.insertFirst(value=3000)
LL.insertFirst(value=3000)
LL.display_status()
print(LL.num_of_node)
print()
LL.delete(3000, delete_all=True)
LL.display()
print()
LL.delete(300)
LL.display()
print()
LL.delete(7000)
LL.display()
print()
LL.append(1e5)
LL.append(1e5)
LL.display()
LL.delete(value=1e5)
LL.display()
print()
LL.delete(value=1e5)
LL.display()
print()
LL.append(1234)
LL.append(1234)
LL.display()
print()
LL.delete(value=1234, delete_all=True)
LL.display()
print()
def dequeue(self):
if self.front >= self.rear:
raise IndexError(" No data is remained")
self.front += 1
return self.data[self.front - 1]
def display(self):
value = self.data[self.front:self.rear]
for idx in range(self.front, self.rear):
print(self.data[idx], end=" ")
return value
class Stack:
def __init__(self, max_size: int):
if not isinstance(max_size, int):
raise ValueError("The size should be an integer")
if max_size <= 0:
raise ValueError("The size should be a positive")
self.data = [0] * max_size
def pop(self):
if self.tail <= 0:
raise IndexError(" No data is remained")
self.tail -= 1
return self.data[self.tail]
class StackByQueue:
def __init__(self, max_size: int, boost_adding: bool = True):
if not isinstance(max_size, int):
raise ValueError("The size should be an integer")
if max_size <= 0:
raise ValueError("The size should be a positive")
def pop(self):
if self.__boost_adding is not True:
return self.__fast_pop()
else:
return self.__slow_pop()
self.current_size += 1
self.temp_data.enqueue(value=value)
while not self.main_data.empty():
self.temp_data.enqueue(value=self.main_data.dequeue())
temp = self.main_data
self.main_data = self.temp_data
self.temp_data = temp
def __fast_pop(self):
if self.main_data.empty() is True:
raise IndexError(" No data is remained")
self.current_size -= 1
return self.main_data.dequeue()
def __slow_pop(self):
if self.main_data.empty() is True:
raise IndexError(" No data is remained")
while self.main_data.size() != 1:
self.temp_data.enqueue(value=self.main_data.dequeue())
value = self.main_data.dequeue()
self.current_size -= 1
temp = self.main_data
self.main_data = self.temp_data
self.temp_data = temp
return value
class QueueByStack:
def __init__(self, max_size: int, boost_adding: bool = True):
if not isinstance(max_size, int):
raise ValueError("The size should be an integer")
if max_size <= 0:
raise ValueError("The size should be a positive")
# You can use normal Python List instead but due to course requirement
def dequeue(self):
if self.__boost_adding is not True:
return self.__fast_dequeue()
else:
return self.__slow_dequeue()
self.current_size += 1
def __fast_dequeue(self):
if self.main_data.empty() is True:
raise IndexError(" No data is remained")
self.current_size -= 1
return self.main_data.pop()
def __slow_dequeue(self):
if self.main_data.empty() is True and self.temp_data.empty() is True:
raise IndexError(" No data is remained")
class CircularQueue:
def __init__(self, max_size: int):
if not isinstance(max_size, int):
raise ValueError("The size should be an integer")
if max_size <= 0:
raise ValueError("The size should be a positive")
self.max_size = max_size
def dequeue(self):
if self.front == -1:
raise MemoryError("No memory left")
temp = self.queue[self.front]
if self.front == self.rear:
self.front = -1
self.rear = -1
else:
self.front = (self.front + 1) % self.max_size
return temp
def display(self):
if self.front == -1:
print("Queue is Empty")
else:
print("Elements in Circular Queue are:", end=" ")
for i in range(self.front, self.max_size):
print(self.queue[i], end=" ")
for i in range(0, self.rear + 1):
print(self.queue[i], end=" ")
print()
➔ From here, please do by yourself, implement Stack by Queue or Queue by Stack by Test Request
• Recursion
def fibonacci(n):
if n in (0, 1):
return n
else:
return fibonacci(n=n-1) + fibonacci(n=n-2)
def fibonacci_iteration(n):
if n in (0, 1):
return n
else:
a, b = 0, 1
for i in range(0, n):
a, b = a + b, a
return a
def tower_hanoi(number_of_disk: int, source: Tuple[List, str], intermediate: Tuple[List, str], target: Tuple[List, str]):
if number_of_disk > 0:
# Move from source to intermediate
tower_hanoi(number_of_disk=number_of_disk - 1, source=source, intermediate=target, target=intermediate)
if source[0] is not None:
data = source[0].pop()
print("MOVING {} at {} to {}".format(data, source[1], target[1]))
target[0].append(data)
# Move from intermediate to target
tower_hanoi(number_of_disk=number_of_disk - 1, source=intermediate, intermediate=source, target=target)
print(source[0], intermediate[0], target[0])
class Node:
def __init__(self, key):
self.left = None
self.right = None
self.val = key
def printInorder(root):
if root:
printInorder(root.left)
print(root.val),
printInorder(root.right)
def printPostorder(root):
if root:
printPostorder(root.left)
printPostorder(root.right)
print(root.val),
def printPreorder(root):
if root:
print(root.val),
printPreorder(root.left)
printPreorder(root.right)