public SkipList(int maxLevels = MAX_LEVELS) { _maxLevels = maxLevels >= 1 && maxLevels <= MAX_LEVELS ? maxLevels : MAX_LEVELS; _head = new Node(int.MinValue + 1, maxLevels); _head.LevelNodes[0] = new LevelNode(_head); _random = new Random(); _currentMaxLevels = 0; }
public void Insert(int value) { var map = new Dictionary<int, int> { { 1, 1 }, { 2, 2 }, { 7, 1 }, { 9, 2 }, { 10, 3 } }; // logN operation int nodeLevels = generateRandomLevelCount(); //map[value]; // avoid going beyond the current max levels if (nodeLevels > _currentMaxLevels) { _head.LevelNodes[_currentMaxLevels] = new LevelNode(_head); // increase the current max level _currentMaxLevels++; nodeLevels = _currentMaxLevels; } var node = new Node(value, nodeLevels); // start scanning from the highest level accessible to this node // need to update later on the skipped nodes for each level // and the next for each node on each level // we cannot do that unless we know how many level 0 nodes were actually skipped var skippedNodesMap = new Dictionary<int, dynamic>(); var countSkippedPerLevel = new int[_currentMaxLevels]; LevelNode pointer = _head.LevelNodes[_currentMaxLevels - 1]; for (var level = _currentMaxLevels - 1; level >= 0; level--) { pointer = pointer.ParentNode.LevelNodes[level]; countSkippedPerLevel[level] = 0; while (pointer.Next != null) { if (pointer.Next.Value > value) { // no need to step away, found our node break; } pointer = pointer.Next; // if we are on the highest level and moving, it means we haven't found the anchor point if (level != _currentMaxLevels - 1) { countSkippedPerLevel[level] += pointer.SkippedNodes + 1; } } if (level < nodeLevels) { // create node if needed var levelNode = new LevelNode(node); levelNode.Next = pointer.Next; node.LevelNodes[level] = levelNode; pointer.Next = levelNode; // will have to update the skipped nodes for this node skippedNodesMap[level] = new { IsNew = true, Node = levelNode }; if (level > 0) { // we'll update this value later levelNode.SkippedNodes = 0; } else { // update values for upper levels for (int i = 1; i < _currentMaxLevels; i++) { dynamic toUpdate = skippedNodesMap[i]; LevelNode nodeToUpdate = toUpdate.Node; if (toUpdate.IsNew) { nodeToUpdate.SkippedNodes = nodeToUpdate.ParentNode.LevelNodes[i - 1].SkippedNodes + countSkippedPerLevel[i - 1]; if (nodeToUpdate.Next != null) { nodeToUpdate.Next.SkippedNodes = nodeToUpdate.Next.SkippedNodes - nodeToUpdate.SkippedNodes; } } else { if (nodeToUpdate.Next != null) { nodeToUpdate.Next.SkippedNodes += 1; } } } } } else { skippedNodesMap[level] = new { IsNew = false, Node = pointer }; } } }