initial upload of all course files

This commit is contained in:
Joe James
2019-05-01 22:08:49 -07:00
committed by GitHub
parent d91f88d3a9
commit 7f2424ce24
15 changed files with 2872 additions and 0 deletions

View File

@@ -0,0 +1,283 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Python List Comprehensions\n",
"basic format: new_list = [transform sequence [filter] ] \n",
"© Joe James, 2019."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import random"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**get values within a range**"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"under_10: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n"
]
}
],
"source": [
"under_10 = [x for x in range(10)]\n",
"print('under_10: ' + str(under_10))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**get squared values**"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"squares: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]\n"
]
}
],
"source": [
"squares = [x**2 for x in under_10]\n",
"print('squares: ' + str(squares))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**get odd numbers using mod**"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"odds: [1, 3, 5, 7, 9]\n"
]
}
],
"source": [
"odds = [x for x in range(10) if x%2 == 1]\n",
"print('odds: ' + str(odds))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**get multiples of 10**"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"ten_x: [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]\n"
]
}
],
"source": [
"ten_x = [x * 10 for x in range(10)]\n",
"print('ten_x: ' + str(ten_x))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**get all numbers from a string**"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"nums: 2073\n"
]
}
],
"source": [
"s = 'I love 2 go t0 the store 7 times a w3ek.'\n",
"nums = [x for x in s if x.isnumeric()]\n",
"print('nums: ' + ''.join(nums))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**get index of a list item**"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"index = 2\n"
]
}
],
"source": [
"names = ['Cosmo', 'Pedro', 'Anu', 'Ray']\n",
"idx = [k for k, v in enumerate(names) if v == 'Anu']\n",
"print('index = ' + str(idx[0]))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**delete an item from a list**"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"['D', 'F', 'E', 'A', 'B', 'C'] ['D', 'F', 'E', 'A', 'B']\n"
]
}
],
"source": [
"letters = [x for x in 'ABCDEF']\n",
"random.shuffle(letters)\n",
"letrs = [a for a in letters if a != 'C']\n",
"print(letters, letrs)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**if-else condition in a comprehension** \n",
"must come before iteration."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"new list: [50, 30, 10, 18, 6, 70]\n"
]
}
],
"source": [
"nums = [5, 3, 10, 18, 6, 7]\n",
"new_list = [x if x%2 == 0 else 10*x for x in nums]\n",
"print('new list: ' + str(new_list))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**nested loop iteration for 2D list** \n",
"b is the subsets, x is the values."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[1, 2, 3, 4]\n"
]
}
],
"source": [
"a = [[1,2],[3,4]]\n",
"new_list = [x for b in a for x in b]\n",
"print(new_list)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

BIN
Section_2/MaxHeap.pdf Normal file

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,346 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Stacks, Queues & Heaps\n",
"© Joe James, 2019.\n",
"\n",
"### Stack using Python List\n",
"Stack is a LIFO data structure -- last-in, first-out. \n",
"Use append() to push an item onto the stack. \n",
"Use pop() to remove an item."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"scrolled": true
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[4, 7, 12, 19]\n"
]
}
],
"source": [
"my_stack = list()\n",
"my_stack.append(4)\n",
"my_stack.append(7)\n",
"my_stack.append(12)\n",
"my_stack.append(19)\n",
"print(my_stack)"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"19\n",
"12\n",
"[4, 7]\n"
]
}
],
"source": [
"print(my_stack.pop())\n",
"print(my_stack.pop())\n",
"print(my_stack)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Stack using List with a Wrapper Class\n",
"We create a Stack class and a full set of Stack methods. \n",
"But the underlying data structure is really a Python List. \n",
"For pop and peek methods we first check whether the stack is empty, to avoid exceptions."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"class Stack():\n",
" def __init__(self):\n",
" self.stack = list()\n",
" def push(self, item):\n",
" self.stack.append(item)\n",
" def pop(self):\n",
" if len(self.stack) > 0:\n",
" return self.stack.pop()\n",
" else:\n",
" return None\n",
" def peek(self):\n",
" if len(self.stack) > 0:\n",
" return self.stack[len(self.stack)-1]\n",
" else:\n",
" return None\n",
" def __str__(self):\n",
" return str(self.stack)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Test Code for Stack Wrapper Class"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[1, 3]\n",
"3\n",
"1\n",
"1\n",
"None\n"
]
}
],
"source": [
"my_stack = Stack()\n",
"my_stack.push(1)\n",
"my_stack.push(3)\n",
"print(my_stack)\n",
"print(my_stack.pop())\n",
"print(my_stack.peek())\n",
"print(my_stack.pop())\n",
"print(my_stack.pop())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"### Queue using Python Deque\n",
"Queue is a FIFO data structure -- first-in, first-out. \n",
"Deque is a double-ended queue, but we can use it for our queue. \n",
"We use append() to enqueue an item, and popleft() to dequeue an item. \n",
"See [Python docs](https://docs.python.org/3/library/collections.html#collections.deque) for deque."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"deque([5, 10])\n",
"5\n"
]
}
],
"source": [
"from collections import deque\n",
"my_queue = deque()\n",
"my_queue.append(5)\n",
"my_queue.append(10)\n",
"print(my_queue)\n",
"print(my_queue.popleft())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Fun exercise:\n",
"Write a wrapper class for the Queue class, similar to what we did for Stack, but using Python deque. \n",
"Try adding enqueue, dequeue, and get_size methods."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Python Single-ended Queue Wrapper Class using Deque\n",
"We rename the append method to enqueue, and popleft to dequeue. \n",
"We also add peek and get_size operations."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
"from collections import deque\n",
"class Queue():\n",
" def __init__(self):\n",
" self.queue = deque()\n",
" self.size = 0\n",
" def enqueue(self, item):\n",
" self.queue.append(item)\n",
" self.size += 1\n",
" def dequeue(self, item):\n",
" if self.size > 0:\n",
" self.size -= 1\n",
" return self.queue.popleft()\n",
" else: \n",
" return None\n",
" def peek(self):\n",
" if self.size > 0:\n",
" ret_val = self.queue.popleft()\n",
" queue.appendleft(ret_val)\n",
" return ret_val\n",
" else:\n",
" return None\n",
" def get_size(self):\n",
" return self.size"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Python MaxHeap\n",
"A MaxHeap always bubbles the highest value to the top, so it can be removed instantly. \n",
"Public functions: push, peek, pop \n",
"Private functions: __swap, __floatUp, __bubbleDown, __str__."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"class MaxHeap:\n",
" def __init__(self, items=[]):\n",
" super().__init__()\n",
" self.heap = [0]\n",
" for item in items:\n",
" self.heap.append(item)\n",
" self.__floatUp(len(self.heap) - 1)\n",
"\n",
" def push(self, data):\n",
" self.heap.append(data)\n",
" self.__floatUp(len(self.heap) - 1)\n",
"\n",
" def peek(self):\n",
" if self.heap[1]:\n",
" return self.heap[1]\n",
" else:\n",
" return False\n",
" \n",
" def pop(self):\n",
" if len(self.heap) > 2:\n",
" self.__swap(1, len(self.heap) - 1)\n",
" max = self.heap.pop()\n",
" self.__bubbleDown(1)\n",
" elif len(self.heap) == 2:\n",
" max = self.heap.pop()\n",
" else: \n",
" max = False\n",
" return max\n",
"\n",
" def __swap(self, i, j):\n",
" self.heap[i], self.heap[j] = self.heap[j], self.heap[i]\n",
"\n",
" def __floatUp(self, index):\n",
" parent = index//2\n",
" if index <= 1:\n",
" return\n",
" elif self.heap[index] > self.heap[parent]:\n",
" self.__swap(index, parent)\n",
" self.__floatUp(parent)\n",
"\n",
" def __bubbleDown(self, index):\n",
" left = index * 2\n",
" right = index * 2 + 1\n",
" largest = index\n",
" if len(self.heap) > left and self.heap[largest] < self.heap[left]:\n",
" largest = left\n",
" if len(self.heap) > right and self.heap[largest] < self.heap[right]:\n",
" largest = right\n",
" if largest != index:\n",
" self.__swap(index, largest)\n",
" self.__bubbleDown(largest)\n",
" \n",
" def __str__(self):\n",
" return str(self.heap)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### MaxHeap Test Code"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"[0, 95, 10, 21, 3]\n",
"95\n",
"21\n"
]
}
],
"source": [
"m = MaxHeap([95, 3, 21])\n",
"m.push(10)\n",
"print(m)\n",
"print(m.pop())\n",
"print(m.peek())"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@@ -0,0 +1,439 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Python Linked Lists"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Node Class\n",
"Node class has a constructor that sets the data passed in, and optionally can set the next_node and prev_node. \n",
"It also has a str method to give a string representation for printing. \n",
"Note that prev_node is only used for Doubly Linked Lists."
]
},
{
"cell_type": "code",
"execution_count": 128,
"metadata": {},
"outputs": [],
"source": [
"class Node:\n",
"\n",
" def __init__ (self, d, n=None, p=None):\n",
" self.data = d\n",
" self.next_node = n\n",
" self.prev_node = p\n",
" \n",
" def __str__ (self):\n",
" return ('(' + str(self.data) + ')')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### LinkedList Class\n",
"A LinkedList object has two attributes: a root node that defaults to None, and size that defaults to 0.\n",
" \n",
"**Add** method receives a piece of data, creates a new Node, setting the root as its next_node, changes the LL's root pointer to the new node, and increments size.\n",
"\n",
"**Find** iterates through the nodes until it finds the data passed in. If if finds the data it will return it, otherwise returns None.\n",
"\n",
"**Remove** needs pointers to this_node and prev_node. If it finds the data, it needs to check if it is in the root node (prev_node is None) before deciding how to bypass the deleted node.\n",
"\n",
"**Print_list** iterates the list and prints each node."
]
},
{
"cell_type": "code",
"execution_count": 129,
"metadata": {},
"outputs": [],
"source": [
"class LinkedList:\n",
"\n",
" def __init__(self, r = None):\n",
" self.root = r\n",
" self.size = 0\n",
"\n",
" def add(self, d):\n",
" new_node = Node(d, self.root)\n",
" self.root = new_node\n",
" self.size += 1\n",
" \n",
" def find(self, d):\n",
" this_node = self.root\n",
" while this_node is not None:\n",
" if this_node.data == d:\n",
" return d\n",
" else:\n",
" this_node = this_node.next_node\n",
" return None\n",
"\n",
" def remove(self, d):\n",
" this_node = self.root\n",
" prev_node = None\n",
"\n",
" while this_node is not None:\n",
" if this_node.data == d:\n",
" if prev_node is not None: # data is in non-root\n",
" prev_node.next_node = this_node.next_node\n",
" else: # data is in root node\n",
" self.root = this_node.next_node\n",
" self.size -= 1\n",
" return True # data removed\n",
" else:\n",
" prev_node = this_node\n",
" this_node = this_node.next_node\n",
" return False # data not found\n",
" \n",
" def print_list(self):\n",
" this_node = self.root\n",
" while this_node is not None:\n",
" print(this_node, end='->')\n",
" this_node = this_node.next_node\n",
" print('None')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Linked List Test Code\n",
"This test code adds nodes to the LinkedList, Prints the list, prints the size, removes an item, and finds an item."
]
},
{
"cell_type": "code",
"execution_count": 130,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(12)->(8)->(5)->None\n",
"size=3\n",
"size=2\n",
"5\n",
"(12)\n"
]
}
],
"source": [
"myList = LinkedList()\n",
"myList.add(5)\n",
"myList.add(8)\n",
"myList.add(12)\n",
"myList.print_list()\n",
"\n",
"print(\"size=\"+str(myList.size))\n",
"myList.remove(8)\n",
"print(\"size=\"+str(myList.size))\n",
"print(myList.find(5))\n",
"print(myList.root)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"-----\n",
"### Circular Linked List\n",
"Includes attributes root and size. \n",
"Includes methods add, find, remove, and print_list."
]
},
{
"cell_type": "code",
"execution_count": 131,
"metadata": {},
"outputs": [],
"source": [
"class CircularLinkedList:\n",
"\n",
" def __init__ (self, r = None):\n",
" self.root = r\n",
" self.size = 0\n",
"\n",
" def add (self, d):\n",
" if self.size == 0:\n",
" self.root = Node(d)\n",
" self.root.next_node = self.root\n",
" else:\n",
" new_node = Node (d, self.root.next_node)\n",
" self.root.next_node = new_node\n",
" self.size += 1\n",
"\n",
" def find (self, d):\n",
" this_node = self.root\n",
" while True:\n",
" if this_node.data == d:\n",
" return d\n",
" elif this_node.next_node == self.root:\n",
" return False\n",
" this_node = this_node.next_node\n",
"\n",
" def remove (self, d):\n",
" this_node = self.root\n",
" prev_node = None\n",
"\n",
" while True:\n",
" if this_node.data == d: # found\n",
" if prev_node is not None:\n",
" prev_node.next_node = this_node.next_node\n",
" else:\n",
" while this_node.next_node != self.root:\n",
" this_node = this_node.next_node\n",
" this_node.next_node = self.root.next_node\n",
" self.root = self.root.next_node\n",
" self.size -= 1\n",
" return True # data removed\n",
" elif this_node.next_node == self.root:\n",
" return False # data not found\n",
" prev_node = this_node\n",
" this_node = this_node.next_node\n",
" \n",
" def print_list (self):\n",
" if self.root is None:\n",
" return\n",
" this_node = self.root\n",
" print (this_node, end='->')\n",
" while this_node.next_node != self.root:\n",
" this_node = this_node.next_node\n",
" print (this_node, end='->')\n",
" print()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Circular Linked List Test Code"
]
},
{
"cell_type": "code",
"execution_count": 132,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"size=5\n",
"8\n",
"False\n",
"(5)->(9)->(8)->(3)->(7)->(5)->(9)->(8)->(3)->\n"
]
}
],
"source": [
"cll = CircularLinkedList()\n",
"for i in [5, 7, 3, 8, 9]:\n",
" cll.add(i)\n",
"\n",
"print(\"size=\"+str(cll.size))\n",
"print(cll.find(8))\n",
"print(cll.find(12))\n",
"\n",
"my_node = cll.root\n",
"print (my_node, end='->')\n",
"for i in range(8):\n",
" my_node = my_node.next_node\n",
" print (my_node, end='->')\n",
"print()"
]
},
{
"cell_type": "code",
"execution_count": 133,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"(5)->(9)->(8)->(3)->(7)->\n",
"False\n",
"size=4\n",
"(9)->(3)->(7)->\n"
]
}
],
"source": [
"cll.print_list()\n",
"cll.remove(8)\n",
"print(cll.remove(15))\n",
"print(\"size=\"+str(cll.size))\n",
"cll.remove(5) # delete root node\n",
"cll.print_list()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"-----\n",
"### Doubly Linked List"
]
},
{
"cell_type": "code",
"execution_count": 134,
"metadata": {},
"outputs": [],
"source": [
"class DoublyLinkedList:\n",
"\n",
" def __init__ (self, r = None):\n",
" self.root = r\n",
" self.last = r\n",
" self.size = 0\n",
"\n",
" def add (self, d):\n",
" if self.size == 0:\n",
" self.root = Node(d)\n",
" self.last = self.root\n",
" else:\n",
" new_node = Node(d, self.root)\n",
" self.root.prev_node = new_node\n",
" self.root = new_node\n",
" self.size += 1\n",
"\n",
" def find (self, d):\n",
" this_node = self.root\n",
" while this_node is not None:\n",
" if this_node.data == d:\n",
" return d\n",
" elif this_node.next_node == None:\n",
" return False\n",
" else:\n",
" this_node = this_node.next_node\n",
"\n",
" def remove (self, d):\n",
" this_node = self.root\n",
" while this_node is not None:\n",
" if this_node.data == d:\n",
" if this_node.prev_node is not None:\n",
" if this_node.next_node is not None: # delete a middle node\n",
" this_node.prev_node.next_node = this_node.next_node\n",
" this_node.next_node.prev_node = this_node.prev_node\n",
" else: # delete last node\n",
" this_node.prev_node.next_node = None\n",
" self.last = this_node.prev_node\n",
" else: # delete root node\n",
" self.root = this_node.next_node\n",
" this_node.next_node.prev_node = self.root\n",
" self.size -= 1\n",
" return True # data removed\n",
" else:\n",
" this_node = this_node.next_node\n",
" return False # data not found\n",
" \n",
" def print_list (self):\n",
" if self.root is None:\n",
" return\n",
" this_node = self.root\n",
" print (this_node, end='->')\n",
" while this_node.next_node is not None:\n",
" this_node = this_node.next_node\n",
" print (this_node, end='->')\n",
" print()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Doubly Linked List Test Code"
]
},
{
"cell_type": "code",
"execution_count": 135,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"size=5\n",
"(9)->(8)->(3)->(9)->(5)->\n",
"size=4\n"
]
}
],
"source": [
"dll = DoublyLinkedList()\n",
"for i in [5, 9, 3, 8, 9]:\n",
" dll.add(i)\n",
"\n",
"print(\"size=\"+str(dll.size))\n",
"dll.print_list()\n",
"dll.remove(8)\n",
"print(\"size=\"+str(dll.size))"
]
},
{
"cell_type": "code",
"execution_count": 136,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"False\n",
"False\n",
"(22)->(21)->(9)->(3)->(9)->\n",
"(3)\n"
]
}
],
"source": [
"print(dll.remove(15))\n",
"print(dll.find(15))\n",
"dll.add(21)\n",
"dll.add(22)\n",
"dll.remove(5)\n",
"dll.print_list()\n",
"print(dll.last.prev_node)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

Binary file not shown.

View File

@@ -0,0 +1,148 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Binary Search Tree\n",
"**Constructor** sets three attributes: data, left subtree and right subtree. \n",
"**Insert** inserts a new subtree into the proper location. \n",
"**Find** finds a value. If value not found, returns False. \n",
"**Get_size** returns the number of nodes in the tree (excluding None nodes). \n",
"**Preorder** prints a preorder traversal of the tree. \n",
"**Inorder** prints an inorder traversal of the tree."
]
},
{
"cell_type": "code",
"execution_count": 69,
"metadata": {},
"outputs": [],
"source": [
"class Tree:\n",
" def __init__(self, data, left=None, right=None):\n",
" self.data = data\n",
" self.left = left\n",
" self.right = right\n",
" def insert(self, data):\n",
" if self.data == data:\n",
" return False # duplicate value\n",
" elif self.data > data:\n",
" if self.left is not None:\n",
" return self.left.insert(data)\n",
" else:\n",
" self.left = Tree(data)\n",
" return True\n",
" else:\n",
" if self.right is not None:\n",
" return self.right.insert(data)\n",
" else:\n",
" self.right = Tree(data)\n",
" return True\n",
" def find(self, data):\n",
" if self.data == data:\n",
" return data\n",
" elif self.data > data:\n",
" if self.left is None:\n",
" return False\n",
" else:\n",
" return self.left.find(data)\n",
" elif self.data < data:\n",
" if self.right is None:\n",
" return False\n",
" else:\n",
" return self.right.find(data)\n",
" def get_size(self):\n",
" if self.left is not None and self.right is not None:\n",
" return 1 + self.left.get_size() + self.right.get_size()\n",
" elif self.left:\n",
" return 1 + self.left.get_size()\n",
" elif self.right:\n",
" return 1 + self.right.get_size()\n",
" else:\n",
" return 1\n",
" def preorder(self):\n",
" if self is not None:\n",
" print (self.data, end=' ')\n",
" if self.left is not None:\n",
" self.left.preorder()\n",
" if self.right:\n",
" self.right.preorder()\n",
" def inorder(self):\n",
" if self is not None:\n",
" if self.left is not None:\n",
" self.left.inorder()\n",
" print (self.data, end=' ')\n",
" if self.right is not None:\n",
" self.right.inorder()\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Test Code\n",
"We create a new tree, insert one value, insert a whole list of values, find all values from 1 to 15 (False for 0, 5 and 8 shows that those values are not in the tree), print the size of the tree, print preorder and postorder traversals."
]
},
{
"cell_type": "code",
"execution_count": 70,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"False 1 2 3 4 False 6 7 False 9 10 11 12 13 14 15 \n",
" 13\n",
"7 2 1 3 6 4 9 15 10 12 11 13 14 \n",
"1 2 3 4 6 7 9 10 11 12 13 14 15 \n"
]
}
],
"source": [
"tree = Tree(7)\n",
"tree.insert(9)\n",
"for i in [15, 10, 2, 12, 3, 1, 13, 6, 11, 4, 14, 9]:\n",
" tree.insert(i)\n",
"for i in range(16):\n",
" print(tree.find(i), end=' ')\n",
"print('\\n', tree.get_size())\n",
"\n",
"tree.preorder()\n",
"print()\n",
"tree.inorder()\n",
"print()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

Binary file not shown.

View File

@@ -0,0 +1,170 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Graph Implementation Using Adjacency Lists\n",
"for an undirected graph. \n",
"© Joe James, 2019."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Vertex Class\n",
"The Vertex class has a constructor that sets the name of the vertex (in our example, just a letter), and creates a new empty set to store neighbors.\n",
"\n",
"The add_neighbor method adds the name of a neighboring vertex to the neighbors set. This set automatically eliminates duplicates."
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [],
"source": [
"class Vertex:\n",
" def __init__(self, n):\n",
" self.name = n\n",
" self.neighbors = set()\n",
" \n",
" def add_neighbor(self, v):\n",
" self.neighbors.add(v)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Graph Class\n",
"The Graph class uses a dictionary to store vertices in the format, vertex_name:vertex_object.\n",
" \n",
"Adding a new vertex to the graph, we first check if the object passed in is a vertex object, then we check if it already exists in the graph. If both checks pass, then we add the vertex to the graph's vertices dictionary.\n",
"\n",
"When adding an edge, we receive two vertex names, we first check if both vertex names are valid, then we add each to the other's neighbors set.\n",
"\n",
"To print the graph, we iterate through the vertices, and print each vertex name (the key) followed by its sorted neighbors list."
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [],
"source": [
"class Graph:\n",
" vertices = {}\n",
" \n",
" def add_vertex(self, vertex):\n",
" if isinstance(vertex, Vertex) and vertex.name not in self.vertices:\n",
" self.vertices[vertex.name] = vertex\n",
" return True\n",
" else:\n",
" return False\n",
" \n",
" def add_edge(self, u, v):\n",
" if u in self.vertices and v in self.vertices:\n",
" self.vertices[u].add_neighbor(v)\n",
" self.vertices[v].add_neighbor(u)\n",
" return True\n",
" else:\n",
" return False\n",
" \n",
" def print_graph(self):\n",
" for key in sorted(list(self.vertices.keys())):\n",
" print(key, sorted(list(self.vertices[key].neighbors)))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Test Code\n",
"Here we create a new Graph object. We create a new vertex named A. We add A to the graph. Then we add new vertex B to the graph. Then we iterate from A to K and add a bunch of vertices to the graph. Since the add_vertex method checks for duplicates, A and B are not added twice."
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [],
"source": [
"g = Graph()\n",
"a = Vertex('A')\n",
"g.add_vertex(a)\n",
"g.add_vertex(Vertex('B'))\n",
"for i in range(ord('A'), ord('K')):\n",
" g.add_vertex(Vertex(chr(i)))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"An edge consists of two vertex names. Here we iterate through a list of edges and add each to the graph. \n",
"\n",
"This print_graph method doesn't give a very good visualization of the graph, but it does show the neighbors for each vertex."
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"A ['B', 'E']\n",
"B ['A', 'F']\n",
"C ['G']\n",
"D ['E', 'H']\n",
"E ['A', 'D', 'H']\n",
"F ['B', 'G', 'I', 'J']\n",
"G ['C', 'F', 'J']\n",
"H ['D', 'E', 'I']\n",
"I ['F', 'H']\n",
"J ['F', 'G']\n"
]
}
],
"source": [
"edges = ['AB', 'AE', 'BF', 'CG', 'DE', 'DH', 'EH', 'FG', 'FI', 'FJ', 'GJ', 'HI']\n",
"for edge in edges:\n",
" g.add_edge(edge[0], edge[1])\n",
"\n",
"g.print_graph()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

View File

@@ -0,0 +1,175 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Graph Implementation Using Adjacency Matrix\n",
"for undirected graph, with weighted or unweighted edges. \n",
"© Joe James, 2019."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Vertex Class\n",
"A vertex object only needs to store its name. "
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"class Vertex:\n",
" def __init__(self, n):\n",
" self.name = n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Graph Class\n",
"A graph object has three attributes: \n",
"**vertices** - a dictionary with vertex_name:vertex_object. \n",
"**edges** - a 2-dimensional list (ie. a matrix) of edges. for an unweighted graph it will contain 0 for no edge and 1 for edge. \n",
"**edge_indices** - a dictionary with vertex_name:list_index (eg. A:0) to access edges. \n",
"add_vertex updates all three of these attributes. \n",
"add_edge only needs to update the edges matrix."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [],
"source": [
"class Graph:\n",
" vertices = {}\n",
" edges = []\n",
" edge_indices = {}\n",
" \n",
" def add_vertex(self, vertex):\n",
" if isinstance(vertex, Vertex) and vertex.name not in self.vertices:\n",
" self.vertices[vertex.name] = vertex\n",
" # for loop appends a column of zeros to the edges matrix\n",
" for row in self.edges:\n",
" row.append(0)\n",
" # append a row of zeros to the bottom of the edges matrix\n",
" self.edges.append([0] * (len(self.edges)+1))\n",
" self.edge_indices[vertex.name] = len(self.edge_indices)\n",
" return True\n",
" else:\n",
" return False\n",
" \n",
" def add_edge(self, u, v, weight=1):\n",
" if u in self.vertices and v in self.vertices:\n",
" self.edges[self.edge_indices[u]][self.edge_indices[v]] = weight\n",
" self.edges[self.edge_indices[v]][self.edge_indices[u]] = weight\n",
" return True\n",
" else:\n",
" return False\n",
" \n",
" def print_graph(self):\n",
" for v, i in sorted(self.edge_indices.items()):\n",
" print(v + ' ', end='')\n",
" for j in range(len(self.edges)):\n",
" print(self.edges[i][j], end=' ')\n",
" print(' ')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Test Code\n",
"Here we create a new Graph object. We create a new vertex named A. We add A to the graph. Then we add new vertex B to the graph. Then we iterate from A to K and add a bunch of vertices to the graph. Since the add_vertex method checks for duplicates, A and B are not added twice.\n",
"This is exactly the same test code we used for the graph with adjacency lists."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"g = Graph()\n",
"a = Vertex('A')\n",
"g.add_vertex(a)\n",
"g.add_vertex(Vertex('B'))\n",
"for i in range(ord('A'), ord('K')):\n",
" g.add_vertex(Vertex(chr(i)))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"An edge consists of two vertex names. Here we iterate through a list of edges and add each to the graph. \n",
"\n",
"This print_graph method doesn't give a very good visualization of the graph, but it does show the adjacency matrix so we can see each vertex's neighbors."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"A 0 1 0 0 1 0 0 0 0 0 \n",
"B 1 0 0 0 0 1 0 0 0 0 \n",
"C 0 0 0 0 0 0 1 0 0 0 \n",
"D 0 0 0 0 1 0 0 1 0 0 \n",
"E 1 0 0 1 0 0 0 1 0 0 \n",
"F 0 1 0 0 0 0 1 0 1 1 \n",
"G 0 0 1 0 0 1 0 0 0 1 \n",
"H 0 0 0 1 1 0 0 0 1 0 \n",
"I 0 0 0 0 0 1 0 1 0 0 \n",
"J 0 0 0 0 0 1 1 0 0 0 \n"
]
}
],
"source": [
"edges = ['AB', 'AE', 'BF', 'CG', 'DE', 'DH', 'EH', 'FG', 'FI', 'FJ', 'GJ', 'HI']\n",
"for edge in edges:\n",
" g.add_edge(edge[0], edge[1])\n",
"\n",
"g.print_graph()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.0"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

BIN
Section_5/Graphs.pdf Normal file

Binary file not shown.

View File

@@ -0,0 +1,47 @@
# implementation of an undirected graph using Adjacency Lists
class Vertex:
def __init__(self, n):
self.name = n
self.neighbors = list()
def add_neighbor(self, v):
if v not in self.neighbors:
self.neighbors.append(v)
self.neighbors.sort()
class Graph:
vertices = {}
def add_vertex(self, vertex):
if isinstance(vertex, Vertex) and vertex.name not in self.vertices:
self.vertices[vertex.name] = vertex
return True
else:
return False
def add_edge(self, u, v):
if u in self.vertices and v in self.vertices:
# my YouTube video shows a silly for loop here, but this is a much faster way to do it
self.vertices[u].add_neighbor(v)
self.vertices[v].add_neighbor(u)
return True
else:
return False
def print_graph(self):
for key in sorted(list(self.vertices.keys())):
print(key + str(self.vertices[key].neighbors))
g = Graph()
# print(str(len(g.vertices)))
a = Vertex('A')
g.add_vertex(a)
g.add_vertex(Vertex('B'))
for i in range(ord('A'), ord('K')):
g.add_vertex(Vertex(chr(i)))
edges = ['AB', 'AE', 'BF', 'CG', 'DE', 'DH', 'EH', 'FG', 'FI', 'FJ', 'GJ', 'HI']
for edge in edges:
g.add_edge(edge[:1], edge[1:])
g.print_graph()

View File

@@ -0,0 +1,49 @@
# implementation of an undirected graph using Adjacency Matrix, with weighted or unweighted edges
class Vertex:
def __init__(self, n):
self.name = n
class Graph:
vertices = {}
edges = []
edge_indices = {}
def add_vertex(self, vertex):
if isinstance(vertex, Vertex) and vertex.name not in self.vertices:
self.vertices[vertex.name] = vertex
for row in self.edges:
row.append(0)
self.edges.append([0] * (len(self.edges)+1))
self.edge_indices[vertex.name] = len(self.edge_indices)
return True
else:
return False
def add_edge(self, u, v, weight=1):
if u in self.vertices and v in self.vertices:
self.edges[self.edge_indices[u]][self.edge_indices[v]] = weight
self.edges[self.edge_indices[v]][self.edge_indices[u]] = weight
return True
else:
return False
def print_graph(self):
for v, i in sorted(self.edge_indices.items()):
print(v + ' ', end='')
for j in range(len(self.edges)):
print(self.edges[i][j], end='')
print(' ')
g = Graph()
# print(str(len(g.vertices)))
a = Vertex('A')
g.add_vertex(a)
g.add_vertex(Vertex('B'))
for i in range(ord('A'), ord('K')):
g.add_vertex(Vertex(chr(i)))
edges = ['AB', 'AE', 'BF', 'CG', 'DE', 'DH', 'EH', 'FG', 'FI', 'FJ', 'GJ', 'HI']
for edge in edges:
g.add_edge(edge[:1], edge[1:])
g.print_graph()