def insert(self, key, data=None): """ Inserts a new node to the skip list. Parameters ========== key Any valid identifier to uniquely identify the node in the linked list. data Any valid data to be stored in the node. """ path = self._search(key) tip = path[-1] below = SkipNode(key=key, data=data, next=tip.next) tip.next = below total_level = self._levels level = 1 while random.getrandbits(1) % 2 == 0 and level <= total_level: if level == total_level: self._add_level() prev = self.head else: prev = path[total_level - 1 - level] below = SkipNode(key=key, data=None, next=prev.next, down=below) prev.next = below level += 1 self._num_nodes += 1
def extract(self, key): """ Extracts the node with the given key in the skip list. Parameters ========== key The key of the node under consideration. Returns ======= return_node: SkipNode The node with given key. """ path = self._search(key) tip = path[-1] if tip.next.key != key: raise KeyError('Node with key %s is not there in %s' % (key, self)) return_node = SkipNode(tip.next.key, tip.next.data) total_level = self._levels level = total_level - 1 while level >= 0 and path[level].next.key == key: path[level].next = path[level].next.next level -= 1 walk = self.head while walk is not None: if walk.next is self.tail: self._levels -= 1 self.head = walk.down self.tail = self.tail.down walk = walk.down else: break self._num_nodes -= 1 if self._levels == 0: self._add_level() return return_node
def _add_level(self): self.tail = SkipNode(math.inf, next=None, down=self.tail) self.head = SkipNode(-math.inf, next=self.tail, down=self.head) self._levels += 1