# Singly-linked list routines # (augmented version of code in Listings 7.1-7.10 of the text) class Node: def __init__(self, initdata): self.data = initdata self.next = None def getData(self): return self.data def getNext(self): return self.next def setData(self, newdata): self.data = newdata def setNext(self, newnext): self.next = newnext class UnorderedList: def __init__(self): self.head = None def isEmpty(self): return self.head == None def add(self, item): # allows duplicates temp = Node(item) temp.setNext(self.head) self.head = temp def addUnique(self, item): # not in book if not self.search(item): self.add(item) 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): # fails if item is not present :-( 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 first(self): # for recursive algorithms; not in book return self.head.getData() def rest(self): # for recursive algorithms; not in book rtn = UnorderedList() rtn.head = self.head.getNext() return rtn def __str__(self): # not in book rtn = "" current = self.head while current != None: rtn += (" " + str(current.getData())) current = current.getNext() return rtn def clone(self): # not in book rtn = UnorderedList() current = self.head while current != None: rtn.add(current.getData()) current = current.getNext() return rtn def merge(self, other): # allows duplicates; not in book # should perhaps be part of a separate "Bag" abstraction, built # on top of linked lists rtn = self.clone() current = other.head while current != None: item = current.getData() rtn.add(item) current = current.getNext() return rtn def union(self, other): # maintains uniqueness; not in book # should perhaps be part of a separate Set abstraction, built # on top of linked lists rtn = self.clone() current = other.head while current != None: item = current.getData() rtn.addUnique(item) current = current.getNext() return rtn class OrderedList(UnorderedList): # inherits all methods of OrderedList that aren't overridden # (re-defined) here def __init__(self): UnorderedList.__init__(self) def search(self, item): 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 add(self, item): # allows duplicates 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 addUnique(self, item): # avoids duplicates; not in book 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() if current == None or current.getData() != item: temp = Node(item) if previous == None: temp.setNext(self.head) self.head = temp else: temp.setNext(current) previous.setNext(temp) def merge(self, other): # allows duplicates; not in book # should perhaps be part of a separate "Bag" abstraction, built # on top of linked lists sc = self.head oc = other.head rtn = OrderedList() rtn.add(0) # dummy node to simplify cases below tail = rtn.head while True: if sc == None: if oc == None: break temp = Node(oc.getData()) oc = oc.getNext() elif oc == None: temp = Node(sc.getData()) sc = sc.getNext() else: sd = sc.getData() od = oc.getData() if od < sd: temp = Node(oc.getData()) oc = oc.getNext() else: temp = Node(sc.getData()) sc = sc.getNext() tail.setNext(temp) tail = temp rtn.head = rtn.head.getNext() return rtn def union(self, other): # maintains uniqueness; not in book # should perhaps be part of a separate Set abstraction, built # on top of linked lists sc = self.head oc = other.head rtn = OrderedList() rtn.add(0) # dummy node to simplify cases below tail = rtn.head while True: if sc == None: if oc == None: break temp = Node(oc.getData()) oc = oc.getNext() elif oc == None: temp = Node(sc.getData()) sc = sc.getNext() else: sd = sc.getData() od = oc.getData() if sd == od: sc = sc.getNext() continue # go back to top of while loop if od < sd: temp = Node(oc.getData()) oc = oc.getNext() else: temp = Node(sc.getData()) sc = sc.getNext() tail.setNext(temp) tail = temp rtn.head = rtn.head.getNext() # discard dummy node return rtn def SLlistsum(l): if l.isEmpty(): return 0 return l.first() + SLlistsum(l.rest())