# -*- coding: utf-8 -*- """ Created on Sat Dec 5 17:18:13 2020 @author: Sam_Yan An implementation of LinkedList in Python """ __all__ = ['LinkedList'] def private(*values): """ For encapsulation of the LinkedList object """ def decorator(cls): class Proxy: def __init__(self, *args, **kwargs): self.proxy = cls(*args, **kwargs) def __call__(self, cls, *args, **kwargs): return self.proxy def __getattr__(self, attr): if attr in values: raise AttributeError("Private valueiables are not accessible!") else: return getattr(self.proxy, attr) def __setattr__(self, attr, val): # Allow access inside the class if attr == 'proxy': self.__dict__[attr] = val elif attr in values: raise AttributeError("Private valueiables are not accessible!") else: setattr(self.proxy, attr, val) def __str__(self): return self.proxy.__str__() return Proxy return decorator @private('data', 'nextNode', 'prevNode') class Node: def __init__(self, data=None, prevNode=None, nextNode=None): self.data = data self.prevNode = prevNode self.nextNode = nextNode def getData(self): return self.data def setData(self, data): self.data = data def getNext(self): return self.nextNode def setNext(self, nextNode): self.nextNode = nextNode def getPrev(self): return self.prevNode def setPrev(self, prevNode): self.prevNode = prevNode def __str__(self): return "Node: " + str(self.data) @private('head', 'tail', 'size') class LinkedList: def __init__(self): self.head = self.tail = None #null self.size = 0 def append(self, data): self.insertAt(self.size, data) def delete(self, data): return self.deleteAt(self.getEleIndex(data)) def getSize(self): return self.size def insertAt(self, index, data): if index > self.size: # throw new Exception("Required index out of bound!"); raise IndexError("Required index out of bound!") newNode = Node(data) if self.size == 0: self.head = self.tail = newNode elif index == 0: # insertion at head: newNode.setNext(self.head) self.head = newNode elif index == self.size: newNode.setPrev(self.tail) self.tail.setNext(newNode) self.tail = newNode else: count, tempNode = 0, self.head while count < index - 1: tempNode = tempNode.getNext() count += 1 newNode.setPrev(tempNode) newNode.setNext(tempNode.getNext()) tempNode.setNext(newNode) self.size += 1 def getEleIndex(self, ele): """ Return the index of the first occurence of the element. If not exists, assume the element will be appended, and therefore return self.size. """ count, temp = 0, self.head while(count < self.size and temp.getData() != ele): temp = temp.getNext() count += 1 if count == self.size: print("Element not exists in the list!") return self.size return count def deleteAt(self, index): if self.size == 0: raise IndexError("All elements have been deleted!") temp = None if index > self.size - 1: raise IndexError("Required index out of bound!") elif index == 0: temp = self.head self.head = self.head.getNext() elif index == self.size - 1: temp = self.tail self.tail = self.tail.getPrev() else: count, temp = 0, self.head while(count < index): temp = temp.getNext() count += 1 temp.getNext().setPrev(temp.getPrev()) temp.getPrev().setNext(temp.getNext()) self.size -= 1 return temp def __str__(self): count, tempNode, printInfo = 0, self.head, "" while(count < self.size): printInfo += (str(tempNode.getData()) + ' ') tempNode = tempNode.getNext() count += 1 return printInfo if __name__ == '__main__': itemlist = LinkedList() itemlist.append(38) itemlist.append(25) itemlist.append(42) itemlist.append(27) print(itemlist) print(itemlist.delete(38)) print(itemlist) print(itemlist.delete(27)) print(itemlist) print(itemlist.delete(42)) print(itemlist) # Lead to exception: print(itemlist.delete(31)) print(itemlist) itemlist.append(12) print(itemlist) print(itemlist.deleteAt(1)) print(itemlist) itemlist.append(38) itemlist.append(42) itemlist.append(27) print(itemlist.deleteAt(2)) print(itemlist) itemlist.insertAt(0, 100) print(itemlist) itemlist.insertAt(1, 50) print(itemlist) itemlist.insertAt(2, 75) print(itemlist) itemlist.insertAt(3, 90) print(itemlist) itemlist.insertAt(itemlist.getSize(), 60) print(itemlist) print(itemlist.getEleIndex(100)) print(itemlist.getEleIndex(60)) print(itemlist.getEleIndex(50)) print(itemlist.getEleIndex(90))