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;
            }
        }