{"cells":[{"cell_type":"markdown","metadata":{},"source":"Linked Structures\n=================\n\n"},{"cell_type":"markdown","metadata":{},"source":["## Agenda\n\n"]},{"cell_type":"markdown","metadata":{},"source":["1. Motives\n2. Objectives\n3. Mechanisms\n4. Linked Data Structures\n\n"]},{"cell_type":"markdown","metadata":{},"source":["## 1. Motives\n\n"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[],"source":["%matplotlib inline\nimport matplotlib.pyplot as plt\nimport numpy as np\nfrom timeit import timeit\n\ndef time_array_front_insert_delete(n):\n return timeit('lst.insert(0, None) ; del lst[0]',\n 'lst = list(range({}))'.format(n),\n number=1000)\n\nns = np.linspace(100, 10000, 50)\nplt.plot(ns, [time_array_front_insert_delete(int(n)) for n in ns], 'ro')\nplt.show()"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[],"source":["# consider:\n\ndef concatenate(arr1, arr2):\n \"\"\"Concatenates the contents of arr1 and arr2 as efficiently (time-wise)\n as possible, so that the resulting structure can be used to index all\n combined elements (arr1's followed by arr2's).\"\"\"\n\n # option 1: O(?)\n for x in arr2:\n arr1.append(x)\n return arr1\n\n # option 2: O(?)\n arr1.extend(arr2)\n return arr1\n\n # option 3: O(?)\n return arr1 + arr2"]},{"cell_type":"markdown","metadata":{},"source":["## 1. Objectives\n\n"]},{"cell_type":"markdown","metadata":{},"source":["We would like a new data storage mechanism for constructing data\nstructures that:\n\n- does not require monolithic, contiguous memory allocation,\n- allows individual elements to be flexibly and efficiently reorganized,\n- and preserves the ability to locate (e.g., via position) and iterate\n\nover elements\n\n"]},{"cell_type":"markdown","metadata":{},"source":["## 1. Mechanisms\n\n"]},{"cell_type":"markdown","metadata":{},"source":["### 3.1. Two-Element Lists\n\n"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[],"source":["# data items\ni1 = 'lions'\ni2 = 'tigers'\ni3 = 'bears'\ni4 = 'oh, my'"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[],"source":["# creating individual \"links\"\nl1 = [,]\nl2 = [,]\nl3 = [,]\nl4 = [,]"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[],"source":["# link-ing them together"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[],"source":["# iteration"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[],"source":["# prepending\n\ni0 = 'walruses'"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[],"source":["# insertion\n\ni2_5 = 'elephants'"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[],"source":["# deletion"]},{"cell_type":"markdown","metadata":{},"source":["### 3.2. \"Link\" objects\n\n"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[],"source":["class Link:\n def __init__(self, val, next=None):\n self.val = val\n self.next = next"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[],"source":["# manually constructing a list"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[],"source":["# prepending\n\ndef prepend(l, val):\n pass"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[],"source":["l = None\nfor x in range(10):\n l = prepend(l, x)"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[],"source":["# iterator\n\ndef link_iterator(l):\n yield"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[],"source":["for x in link_iterator(l):\n print(x)"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[],"source":["# iteration based on a recursive pattern\n\ndef link_iterator_rec(l):\n yield"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[],"source":["for x in link_iterator_rec(l):\n print(x)"]},{"cell_type":"markdown","metadata":{},"source":["## 1. Linked Data Structures\n\n"]},{"cell_type":"markdown","metadata":{},"source":["### 4.1 Linked List\n\n"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[],"source":["class LinkedList:\n class Link:\n def __init__(self, val, next=None):\n self.val = val\n self.next = next\n\n def __init__(self):\n self.head = None\n\n def prepend(self, val):\n pass\n\n def __iter__(self):\n pass\n\n def __repr__(self):\n return '[' + ', '.join(str(x) for x in self) + ']'"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[],"source":["l = LinkedList()\nfor x in range(10):\n l.prepend(x)\nl"]},{"cell_type":"markdown","metadata":{},"source":["### 4.2 Binary Tree\n\n"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[],"source":["class BinaryLink:\n def __init__(self, val, left=None, right=None):\n self.val = val\n self.left = left\n self.right = right"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[],"source":["# manual construction of a \"tree\" representing the expression ((5+3)*(8-4))\nt = BinaryLink('*')\nt.left = BinaryLink('+')\nt.left.left = BinaryLink('5')\nt.left.right = BinaryLink('3')\nt.right = BinaryLink('-')\nt.right.left = BinaryLink('8')\nt.right.right = BinaryLink('4')"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[],"source":["def print_expr_tree(t):\n if t:\n if not t.val.isdigit():\n print('(', end='')\n print_expr_tree(t.left)\n print(t.val, end='')\n print_expr_tree(t.right)\n if not t.val.isdigit():\n print(')', end='')"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[],"source":["print_expr_tree(t)"]},{"cell_type":"markdown","metadata":{},"source":["### 4.3 N-ary Tree\n\n"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[],"source":["class NaryLink:\n def __init__(self, val, n=2):\n self.val = val\n self.children = [None] * n\n\n def __getitem__(self, idx):\n return self.children[idx]\n\n def __setitem__(self, idx, val):\n self.children[idx] = val\n\n def __iter__(self):\n for c in self.children:\n yield c"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[],"source":["root = NaryLink('Kingdoms', n=5)\n\nroot[0] = NaryLink('Animalia', n=35)\nroot[1] = NaryLink('Plantae', n=12)\nroot[2] = NaryLink('Fungi', n=7)\nroot[3] = NaryLink('Protista', n=5)\nroot[4] = NaryLink('Monera', n=5)\n\nroot[2][0] = NaryLink('Chytridiomycota')\nroot[2][1] = NaryLink('Blastocladiomycota')\nroot[2][2] = NaryLink('Glomeromycota')\nroot[2][3] = NaryLink('Ascomycota')\nroot[2][4] = NaryLink('Basidiomycota')\nroot[2][5] = NaryLink('Microsporidia')\nroot[2][6] = NaryLink('Neocallimastigomycota')\n\ndef tree_iter(root):\n if root:\n yield root.val\n for c in root:\n yield from tree_iter(c)"]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[],"source":["for x in tree_iter(root):\n print(x)"]}],"metadata":{"org":null,"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.5.2"}},"nbformat":4,"nbformat_minor":0}