public void Enqueue(string word, double priority) { if (_numNodes >= _nodes.Length - 1) { if (priority > First.Similarity) { Dequeue(); _extras.Clear(); } else if (priority + 0.0000000001 > First.Similarity) { _extras.Add(new WordSimilarityNode { Similarity = priority, Word = word }); return; } else { return; } } var node = new WordSimilarityNode { Similarity = priority, Word = word }; _numNodes++; _nodes[_numNodes] = node; node.QueueIndex = _numNodes; CascadeUp(_nodes[_numNodes]); }
private void CascadeDown(WordSimilarityNode node) { //aka Heapify-down var finalQueueIndex = node.QueueIndex; while (true) { var newParent = node; var childLeftIndex = 2 * finalQueueIndex; //Check if the left-child is higher-priority than the current node if (childLeftIndex > _numNodes) { //This could be placed outside the loop, but then we'd have to check newParent != node twice node.QueueIndex = finalQueueIndex; _nodes[finalQueueIndex] = node; break; } var childLeft = _nodes[childLeftIndex]; if (childLeft.Similarity < newParent.Similarity) { newParent = childLeft; } //Check if the right-child is higher-priority than either the current node or the left child var childRightIndex = childLeftIndex + 1; if (childRightIndex <= _numNodes) { var childRight = _nodes[childRightIndex]; if (childRight.Similarity < newParent.Similarity) { newParent = childRight; } } //If either of the children has higher (smaller) priority, swap and continue cascading if (newParent != node) { //Move new parent to its new index. node will be moved once, at the end //Doing it this way is one less assignment operation than calling Swap() _nodes[finalQueueIndex] = newParent; var temp = newParent.QueueIndex; newParent.QueueIndex = finalQueueIndex; finalQueueIndex = temp; } else { //See note above node.QueueIndex = finalQueueIndex; _nodes[finalQueueIndex] = node; break; } } }
private void Swap(WordSimilarityNode node1, WordSimilarityNode node2) { //Swap the nodes _nodes[node1.QueueIndex] = node2; _nodes[node2.QueueIndex] = node1; //Swap their indicies var temp = node1.QueueIndex; node1.QueueIndex = node2.QueueIndex; node2.QueueIndex = temp; }
//Performance appears to be slightly better when this is NOT inlined o_O private void CascadeUp(WordSimilarityNode node) { //aka Heapify-up var parent = node.QueueIndex / 2; while (parent >= 1) { var parentNode = _nodes[parent]; if (parentNode.Similarity < node.Similarity) { break; } //Node has lower priority value, so move it up the heap Swap(node, parentNode); //For some reason, this is faster with Swap() rather than (less..?) individual operations, like in CascadeDown() parent = node.QueueIndex / 2; } }