{ "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 }