diff --git a/book/book_second_edition.pdf b/book/book_second_edition.pdf index 442a30b..c8dee89 100644 Binary files a/book/book_second_edition.pdf and b/book/book_second_edition.pdf differ diff --git a/src/abstract_structures/linked_list/check_pal.py b/src/abstract_structures/linked_list/check_pal.py index 5bf971e..4e8eb76 100644 --- a/src/abstract_structures/linked_list/check_pal.py +++ b/src/abstract_structures/linked_list/check_pal.py @@ -1,40 +1,49 @@ -#!/usr/bin/python3 -# mari von steinkirch @2013 -# steinkirch at gmail +#!/usr/bin/python + +__author__ = "Mari Wahl" +__email__ = "marina.w4hl@gmail.com" ''' Given a linked list, check if the nodes form a palindrome ''' -from linked_list_fifo import LinkList, Node +from linked_list_fifo import LinkedListFIFO, Node +from node import Node + +def isPal(l): + + if len(l1) < 2: + return True + if l1[0] != l1[-1]: + return False -def isPal(l1): - if len(l1) < 2: return True - if l1[0] != l1[-1]: return False return isPal(l1[1:-1]) - - + + def checkllPal(ll): node = ll.head - l1 = [] + l = [] + while node: - l1.append(node.value) - node = node.next - return isPal(l1) + l.append(node.value) + node = node.pointer - + return isPal(l) -def main(): - ll = LinkList() + + + + +if __name__ == '__main__': + + ll = LinkedListFIFO() l1 = [1, 2, 3, 2, 1] + for i in l1: ll.addNode(i) - print(checkllPal(ll)) - + + assert(checkllPal(ll) == True) + ll.addNode(2) ll.addNode(3) - print(checkllPal(ll)) - - -if __name__ == '__main__': - main() + assert(checkllPal(ll) == False) diff --git a/src/abstract_structures/linked_list/circ_ll.py b/src/abstract_structures/linked_list/circ_ll.py deleted file mode 100644 index ba6d3b3..0000000 --- a/src/abstract_structures/linked_list/circ_ll.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/python3 -# mari von steinkirch @2013 -# steinkirch at gmail - - -''' Build a class for a circular linked list and implement a function to see whether - a linked list is circular''' - -from linked_list_fifo import Node, LinkList - -class Node(object): - def __init__(self, value = None, next = None): - self.value = value - self.next = next - - -class CircLinkList(object): - def __init__(self): - self.head = None - self.tail = None - self.lenght = 0 - - def addNode(self, value): - node = Node(value, self.head) - if not self.head: - self.head = node - if self.tail: - self.tail.next = node - self.tail = node - self.lenght += 1 - - def printList(self): - size = self.lenght - node = self.head - i = 0 - while i < size: - print(node.value) - node = node.next - i += 1 - - - -def isCircularll(ll): - p1 = ll.head - p2 = ll.head - - while p2 and p2.next: - p1 = p1.next - p2 = p2.next.next - - if p1 == p2: - return True - return False - -def main(): - ll = CircLinkList() - for i in range(10): - ll.addNode(i) - ll.printList() - - print(isCircularll(ll)) - - ll2 = LinkList() - for i in range(10): - ll2.addNode(i) - ll2.printList() - - print(isCircularll(ll2)) - - -if __name__ == '__main__': - main() diff --git a/src/abstract_structures/linked_list/circular_ll.py b/src/abstract_structures/linked_list/circular_ll.py new file mode 100644 index 0000000..1330701 --- /dev/null +++ b/src/abstract_structures/linked_list/circular_ll.py @@ -0,0 +1,57 @@ +#!/usr/bin/python + +__author__ = "Mari Wahl" +__email__ = "marina.w4hl@gmail.com" + + + +''' implement a function to see whether a linked list is circular. + To implement this, we just need two pointers with different + paces (for example, one goes twice faster)''' + +from linked_list_fifo import LinkedListFIFO +from node import Node + + +class cicularLinkedListFIFO(LinkedListFIFO): + def _add(self, value): + self.length += 1 + node = Node(value, self.head) + if self.tail: + self.tail.pointer = node + self.tail = node + + + + +def isCircularll(ll): + p1 = ll.head + p2 = ll.head + + while p2: + try: + p1 = p1.pointer + p2 = p2.pointer.pointer + except: + break + + if p1 == p2: + return True + return False + + + +if __name__ == '__main__': + + ll = LinkedListFIFO() + for i in range(10): + ll.addNode(i) + ll._printList() + + print(isCircularll(ll)) + + lcirc = cicularLinkedListFIFO() + for i in range(10): + lcirc.addNode(i) + print(isCircularll(lcirc)) + diff --git a/src/abstract_structures/linked_list/double_linked_list_fifo.py b/src/abstract_structures/linked_list/double_linked_list_fifo.py index 349ead6..8546164 100644 --- a/src/abstract_structures/linked_list/double_linked_list_fifo.py +++ b/src/abstract_structures/linked_list/double_linked_list_fifo.py @@ -1,53 +1,92 @@ -#!/usr/bin/python3 -# mari von steinkirch @2013 -# steinkirch at gmail +#!/usr/bin/python -''' Implement a double-linked list, which is very simple, we just need inherets from a Linked List Class and add an attribute for prev.''' +__author__ = "Mari Wahl" +__email__ = "marina.w4hl@gmail.com" + +''' Implement a double-linked list, which is very simple, we just need inherits +from a Linked List Class and add an attribute for previous.''' + +from linked_list_fifo import LinkedListFIFO -from linked_list_fifo import LinkList class dNode(object): - def __init__(self, value = None, next = None): + def __init__(self, value=None, pointer=None, previous=None): self.value = value - self.next = next - self.prev = None # THIS IS THE EXTRA ATTRIBUTE FOR DOUBLE L - self.children = None # THIS IS NOT USED HERE, IS EXAMPLES WITH MANY LL INSIDE LLs - -class dLinkList(LinkList): - - def addNode(self, value): - node = dNode(value) - if not self.head: - self.head = node - if self.tail: - node.prev = self.tail # ADD THIS WHEN DOUBLE L - self.tail.next = node - self.tail = node - self.length += 1 - - - def printListInverse(self): # THIS IS THE EXTRA METHOD FOR DOUBLE L + self.pointer = pointer + self.previous = previous + + +class dLinkList(LinkedListFIFO): + + # print each node's value, starting from tail + def printListInverse(self): node = self.tail while node: print(node.value) - node = node.prev - - - + try: + node = node.previous + except: + break -from collections import Counter + # add a node in a position different from head, + # ie, in the end of the list + def _add(self, value): + self.length += 1 + node = dNode(value) + if self.tail: + self.tail.pointer = node + node.previous = self.tail + self.tail = node + + # delete a node in some position + def _delete(self, node): + self.length -= 1 + node.previous.pointer = node.pointer + if not node.pointer: + self.tail = node.previous + + # locate node with some index + def _find(self, index): + node = self.head + i = 0 + while node and i < index: + node = node.pointer + i += 1 + return node, i + + # delete nodes in general + def deleteNode(self, index): + if not self.head or not self.head.pointer: + self._deleteFirst() + else: + node, i = self._find(index) + if i == index: + self._delete(node) + else: + print('Node with index {} not found'.format(index)) + + + + + + + +if __name__ == '__main__': + + from collections import Counter -def main(): - ll = dLinkList() - for i in range(1, 10): + for i in range(1, 5): ll.addNode(i) print('Printing the list...') - ll.printList() + ll._printList() print('Now, printing the list inversely...') ll.printListInverse() - - - -if __name__ == '__main__': - main() + print('The list after adding node with value 15') + ll._add(15) + ll._printList() + print("The list after deleting everything...") + for i in range(ll.length-1, -1, -1): + ll.deleteNode(i) + ll._printList() + diff --git a/src/abstract_structures/linked_list/find_kth.py b/src/abstract_structures/linked_list/find_kth.py deleted file mode 100644 index bcac35c..0000000 --- a/src/abstract_structures/linked_list/find_kth.py +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/python3 -# mari von steinkirch @2013 -# steinkirch at gmail - -''' Find the mth-to-last element of a linked list. - One option is having two pointers, separated by m. P1 start at the roots (p1 = self.root) and p2 is m-behinf pointer, which is created when p1 is at m. When p1 reach the end, p2 is the node. ''' - -from linked_list_fifo import Node - -class LinkList(object): - def __init__(self): - self.head = None - self.tail = None - self.lenght = 0 - - def addNode(self, value): - node = Node(value) - if not self.head: - self.head = node - if self.tail: - self.tail.next = node - self.tail = node - self.lenght += 1 - - def removeNode(self, index): - prev = None - node = self.head - i = 0 - while node and i < index: - prev = node - node = node.next - i += 1 - if i == index: - if not prev: - self.head = node.next - else: - prev.next = node.next - self.lenght -= 1 - else: - print('Index not found') - - def findkth_from_begin(self, k): - node = self.head - i = 0 - while node and i < k: - node = node.next - i += 1 - while node: - print(node.value) - node = node.next - - def findkth_to_last(self, k): - node = self.head - key = self.lenght - k - i = 0 - while node and i < key: - node = node.next - i += 1 - print(node.value) - - def findkth_to_last_2pointers(self, k): - node = self.head - pointer = self.head - i = 0 - while pointer and i < k: - pointer = pointer.next - i += 1 - while pointer: - node = node.next - pointer = pointer.next - print(node.value) - - def findkth_to_last_2pointers2(self, k): - p1 = self.head - p2 = self.head - i = 0 - while p1: - if i >= k: # ---> notice >= not >! - p2 = p2.next - p1 = p1.next - i += 1 - print(p2.value) - - -def main(): - ll = LinkList() - for i in range(1, 11): - ll.addNode(i) - # list is 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 - # so 0th from last is 11, 1th to last is 10, - # 2th from last is 9! - - - print('Finding from begin...') - ll.findkth_from_begin(2) - print('Finding to last, case 1...') - ll.findkth_to_last(2) #9 - print('Finding to last, case 2...') - ll.findkth_to_last_2pointers(2) - print('Finding to last, case 3...') - ll.findkth_to_last_2pointers2(2) - -if __name__ == '__main__': - main() - diff --git a/src/abstract_structures/linked_list/find_kth_from_the_end.py b/src/abstract_structures/linked_list/find_kth_from_the_end.py new file mode 100644 index 0000000..4937bc4 --- /dev/null +++ b/src/abstract_structures/linked_list/find_kth_from_the_end.py @@ -0,0 +1,42 @@ +#!/usr/bin/python + +__author__ = "Mari Wahl" +__email__ = "marina.w4hl@gmail.com" + +''' Find the mth-to-last element of a linked list. + One option is having two pointers, separated by m. P1 start at the roots + (p1 = self.root) and p2 is m-behinf pointer, which is created when p1 is at m. + When p1 reach the end, p2 is the node. ''' + +from linked_list_fifo import LinkedListFIFO +from node import Node + + +class LinkedListFIFO_find_kth(LinkedListFIFO): + + + def find_kth_to_last(self, k): + p1, p2 = self.head, self.head + i = 0 + while p1: + if i > k: + try: + p2 = p2.pointer + except: + break + p1 = p1.pointer + i += 1 + return p2.value + + + +if __name__ == '__main__': + ll = LinkedListFIFO_find_kth() + for i in range(1, 11): + ll.addNode(i) + print('The Linked List:') + print(ll._printList()) + k = 3 + k_from_last = ll.find_kth_to_last(k) + print("The %dth element to the last of the LL of size %d is %d" %(k, ll.length, k_from_last)) + diff --git a/src/abstract_structures/linked_list/linkedlist.py b/src/abstract_structures/linked_list/linkedlist.py deleted file mode 100644 index c8049c8..0000000 --- a/src/abstract_structures/linked_list/linkedlist.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/python3 -# mari von steinkirch @2013 -# steinkirch at gmail - -from node import Node - -class UnorderedList(object): - def __init__(self): - self.head = None - - def add(self, item): - temp = Node(item) - temp.setNext(self.head) - self.head = temp - - def length(self): - current = self.head - count = 0 - while current != None: - count = count + 1 - current = current.getNext() - return count - - def search(self, item): - current = self.head - found = False - while current != None and not found: - if current.getData() == item: - found = True - else: - current = current.getNext() - return found - - def remove(self, item): - current = self.head - previous = None - found = False - while not found: - if current.getData() == item: - found = True - else: - previous = current - current = current.getNext() - if previous == None: - self.head = current.getNext() - else: - previous.setNext(current.getNext()) - - -def test_UnorderedList(module_name='this module'): - llist = UnorderedList() - llist.add(31) - llist.add(22) - llist.add(10) - assert(llist.search(22) == True) - llist.remove(22) - assert(llist.search(22) == False) - s = 'Tests in {name} have {con}!' - print(s.format(name=module_name, con='passed')) - - -if __name__ == '__main__': - test_UnorderedList() - - diff --git a/src/abstract_structures/linked_list/ordered_list.py b/src/abstract_structures/linked_list/ordered_list.py deleted file mode 100644 index 50ab9ca..0000000 --- a/src/abstract_structures/linked_list/ordered_list.py +++ /dev/null @@ -1,97 +0,0 @@ -#!/usr/bin/python3 -# mari von steinkirch @2013 -# steinkirch at gmail - - - -from Node import Node - -class OrderedList: - """ The structure of an ordered list is a collection of items where each item - holds a relative position that is based upon some underlying characteristic of - the item. The ordering is typically either ascending or descending and we assume - that list items have a meaningful comparison operation that is already defined. - Many of the ordered list operations are the same as those of the unordered list. - """ - def __init__(self): - self.head = None - - - def add(self,item): - ''' this method is different from linked list ''' - current = self.head - previous = None - stop = False - while current != None and not stop: - if current.getData() > item: - stop = True - else: - previous = current - current = current.getNext() - temp = Node(item) - if previous == None: - temp.setNext(self.head) - self.head = temp - else: - temp.setNext(current) - previous.setNext(temp) - - - def length(self): - current = self.head - count = 0 - while current != None: - count = count + 1 - current = current.getNext() - return count - - - def search(self,item): - ''' this method is different from linked list ''' - current = self.head - found = False - stop = False - while current != None and not found and not stop: - if current.getData() == item: - found = True - else: - if current.getData() > item: - stop = True - else: - current = current.getNext() - return found - - - def remove(self,item): - current = self.head - previous = None - found = False - while not found: - if current.getData() == item: - found = True - else: - previous = current - current = current.getNext() - if previous == None: - self.head = current.getNext() - else: - previous.setNext(current.getNext()) - - - -def test_OrderedList(module_name='this module'): - olist = OrderedList() - olist.add(31) - olist.add(22) - olist.add(10) - assert(olist.search(22) == True) - olist.remove(22) - assert(olist.search(22) == False) - s = 'Tests in {name} have {con}!' - print(s.format(name=module_name, con='passed')) - - -if __name__ == '__main__': - test_OrderedList() - - diff --git a/src/abstract_structures/linked_list/part_linked_list.py b/src/abstract_structures/linked_list/part_linked_list.py new file mode 100644 index 0000000..f38cd62 --- /dev/null +++ b/src/abstract_structures/linked_list/part_linked_list.py @@ -0,0 +1,58 @@ +#!/usr/bin/python + +__author__ = "Mari Wahl" +__email__ = "marina.w4hl@gmail.com" + +''' This function divides a linked list in a value, where everything smaller than this value + goes to the front, and everything large goes to the back:''' + + +from linked_list_fifo import LinkedListFIFO +from node import Node + + +def partList(ll, n): + + more = LinkedListFIFO() + less = LinkedListFIFO() + + node = ll.head + + while node: + item = node.value + + if item < n: + less.addNode(item) + + elif item > n: + more.addNode(item) + + node = node.pointer + + less.addNode(n) + nodemore = more.head + + while nodemore: + less.addNode(nodemore.value) + nodemore = nodemore.pointer + + return less + + + + +if __name__ == '__main__': + + ll = LinkedListFIFO() + l = [6, 7, 3, 4, 9, 5, 1, 2, 8] + for i in l: + ll.addNode(i) + + print('Before Part') + ll._printList() + + print('After Part') + newll = partList(ll, 6) + newll._printList() + + diff --git a/src/abstract_structures/linked_list/part_ll.py b/src/abstract_structures/linked_list/part_ll.py deleted file mode 100644 index 520e885..0000000 --- a/src/abstract_structures/linked_list/part_ll.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/python3 -# mari von steinkirch @2013 -# steinkirch at gmail - -''' This function partionate a linked list in a value, where everything smaller than this value - goes to the front, and everything large goes to the back:''' - -from linked_list_fifo import LinkList, Node - -def partList(ll, n): - more = LinkList() - less = LinkList() - node_old = ll.head - while node_old: - item = node_old.value - if item < n: - less.addNode(item) - elif item > n: - more.addNode(item) - node_old = node_old.next - - less.addNode(n) - nodemore = more.head - while nodemore: - less.addNode(nodemore.value) - nodemore = nodemore.next - return less - - - -def main(): - ll = LinkList() - l1 = [6, 7, 3, 4, 9, 5, 1, 2, 8] - for i in l1: - ll.addNode(i) - print('Before Part') - ll.printList() - print('After Part') - newll = partList(ll, 6) - newll.printList() - - -if __name__ == '__main__': - main() - diff --git a/src/abstract_structures/linked_list/sum_linked_list.py b/src/abstract_structures/linked_list/sum_linked_list.py new file mode 100644 index 0000000..1c48c43 --- /dev/null +++ b/src/abstract_structures/linked_list/sum_linked_list.py @@ -0,0 +1,86 @@ +#!/usr/bin/python + +__author__ = "Mari Wahl" +__email__ = "marina.w4hl@gmail.com" + +''' Supposing two linked lists representing numbers, such that in each of their + nodes they carry one digit. This function sums the two numbers that these + two linked lists represent, returning a third list representing the sum:''' + + +from linked_list_fifo import LinkedListFIFO +from node import Node + + +class LinkedListFIFOYield(LinkedListFIFO): + + # print each node's value, starting from the head + def _printList(self): + node = self.head + while node: + yield(node.value) + node = node.pointer + + + +def sumlls(l1, l2): + + lsum = LinkedListFIFOYield() + dig1 = l1.head + dig2 = l2.head + pointer = 0 + + while dig1 and dig2: + d1 = dig1.value + d2 = dig2.value + sum_d = d1 + d2 + pointer + if sum_d > 9: + pointer = sum_d//10 + lsum.addNode(sum_d%10) + + else: + lsum.addNode(sum_d) + pointer = 0 + + dig1 = dig1.pointer + dig2 = dig2.pointer + + if dig1: + sum_d = pointer + dig1.value + if sum_d > 9: + lsum.addNode(sum_d%10) + else: + lsum.addNode(sum_d) + dig1 = dig1.pointer + + if dig2: + sum_d = pointer + dig2.value + if sum_d > 9: + lsum.addNode(sum_d%10) + else: + lsum.addNode(sum_d) + dig2 = dig2.pointer + + return lsum + + + + + + +if __name__ == '__main__': + l1 = LinkedListFIFOYield() # 2671 + l1.addNode(1) + l1.addNode(7) + l1.addNode(6) + l1.addNode(2) + + l2 = LinkedListFIFOYield() # 455 + l2.addNode(5) + l2.addNode(5) + l2.addNode(4) + + lsum = sumlls(l1, l2) + l = list(lsum._printList()) + for i in reversed(l): + print i diff --git a/src/abstract_structures/linked_list/sum_ll.py b/src/abstract_structures/linked_list/sum_ll.py deleted file mode 100644 index 504d627..0000000 --- a/src/abstract_structures/linked_list/sum_ll.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/python3 -# mari von steinkirch @2013 -# steinkirch at gmail - -''' Supposing two linked lists represening numbers, such that in each of their - nodes they carry one digit. This function sums the two numbers that these - two linked lists represent, returning a third list representing the sum:''' - -from linked_list_fifo import Node, LinkList - - -def sumlls(l1, l2): - lsum = LinkList() - dig1 = l1.head - dig2 = l2.head - next = 0 - while dig1 and dig2: - d1 = dig1.value - d2 = dig2.value - sum_d = d1 + d2 + next - if sum_d > 9: - next = sum_d//10 - lsum.addNode(sum_d%10) - - else: - lsum.addNode(sum_d) - next = 0 - - dig1 = dig1.next - dig2 = dig2.next - - if dig1: - sum_d = next + dig1.value - if sum_d > 9: - lsum.addNode(sum_d%10) - else: - lsum.addNode(sum_d) - dig1 = dig1.next - - if dig2: - sum_d = next + dig2.value - if sum_d > 9: - lsum.addNode(sum_d%10) - else: - lsum.addNode(sum_d) - dig2 = dig2.next - - - return lsum - - - -def main(): - l1 = LinkList() # 2671 - l1.addNode(1) - l1.addNode(7) - l1.addNode(6) - l1.addNode(2) - - l2 = LinkList() # 455 - l2.addNode(5) - l2.addNode(5) - l2.addNode(4) - - lsum = sumlls(l1, l2) - lsum.printList()# 3126 - - -if __name__ == '__main__': - main()