DATA STRUCTURES IN PYTHON DLL PLEASE DO NOT COPY AND PASTE FROM PREVIOUS CHEGG ANSWERS I'VE CHECKED THEM ALL THEY'RE WRONG DO NOT USE ANY OTHER DATA STRUCTURE THAN DLL (MEANING NO LISTS, DICTIONARIES) PLEASE ADD THE FUNCTIONS TO THE CODE AND MAKE SURE IT RUNS #CODE class DLL: class _Node: def __init__(self, data, next=None, prev=None): self._data = data self._next = next self._prev = prev def __str__(self): return '({0})'.format(self._data) def __init__(self): self._h = None self._t = None self._size = 0 def __str__(self): st = "List=<" curr = self._h while curr is not None: st = st + str(curr._data) # st = st + str(curr) if curr._next is not None: st = st + "," curr = curr._next return st+">" def __contains__(self, val): curr = self._h while curr is not None: if curr._data == val: return True curr = curr._next return False def isEmpty(self): return self._h is None def headNode(self): return self._h def tailNode(self): return self._t def head_val(self): if not self.isEmpty(): return self._h._data else: raise TypeError("None value") def tail_val(self): if not self.isEmpty(): return self._t._data else: raise TypeError("None value") def printF(self): p = self._h while p is not None: print(p._data, end=",") p = p._next print() def printR(self): p = self._t while p is not None: print(p._data, end=",") p = p._prev print() def addToHead(self, data): newNode = self._Node(data, self._h, None) if self._h is not None: self._h._prev = newNode self._h = newNode if self._t is None: self._t = self._h self._size += 1 def addToTail(self, data): newNode = self._Node(data, None, self._t) if self._t is not None: self._t._next = newNode self._t = newNode if self._h is None: self._h = newNode self._size += 1 def removeHead(self): if self.isEmpty(): raise TypeError("Empty") if self._h == self._t: # one Node self._h = self._t = None else: self._h = self._h._next self._h._prev = None self._size -= 1 def removeTail(self): if self.isEmpty(): raise TypeError("Empty") if self._h == self._t: # one Node self._h = self._t = None else: self._t = self._t._prev self._t._next = None self._size -= 1 def clear(self): self._h = self._t = None self._size = 0 def remove(self, val): if self.isEmpty(): return False if self._h._data == val: self.removeHead() return True # if self._h == self._t: # one Node # return False curr = self._h #._next while curr._next is not None: if curr._data == val: curr._prev._next = curr._next curr._next._prev = curr._prev self._size -= 1 return True curr = curr._next if self._t._data == val: self.removeTail() return True return False def __len__(self): return self._size def __setitem__(self, k, val): if k < 0: raise IndexError("Index error < 0") if k >= self._size: raise IndexError("Index error > len") curr = self._h c = 0 while curr is not None: if c == k: curr._data = val return else: c += 1 curr = curr._next def __getitem__(self, k): if k < 0: raise IndexError("Index error < 0") if k >= self._size: raise IndexError("Index error > len") curr = self._h c.