/// <summary>Adds an item to the heap.</summary> /// <param name="key">The key for this entry.</param> /// <param name="value">The value for this entry.</param> public virtual void Insert(IComparable key, object value) { // Create the entry based on the provided key and value ChoBinaryHeapEntry entry = new ChoBinaryHeapEntry(key, value); // Add the item to the list, making sure to keep track of where it was added. int pos = _list.Add(entry); // don't actually need it inserted yet, but want to make sure there's enough space for it // If it was added at the beginning, i.e. this is the only item, we're done. if (pos == 0) { return; } // Otherwise, perform log(n) operations, walking up the tree, swapping // where necessary based on key values while (pos > 0) { // Get the next position to check int nextPos = pos / 2; // Extract the entry at the next position ChoBinaryHeapEntry toCheck = (ChoBinaryHeapEntry)_list[nextPos]; // Compare that entry to our new one. If our entry has a larger key, move it up. // Otherwise, we're done. if (entry.CompareTo(toCheck) > 0) { _list[pos] = toCheck; pos = nextPos; } else { break; } } // Make sure we put this entry back in, just in case _list[pos] = entry; }
/// <summary>Removes the entry at the top of the heap.</summary> /// <returns>The removed entry.</returns> public virtual object Remove() { // Get the first item and save it for later (this is what will be returned). if (_list.Count == 0) { throw new InvalidOperationException("Cannot remove an item from the heap as it is empty."); } object toReturn = ((ChoBinaryHeapEntry)_list[0]).Value; // Remove the first item _list.RemoveAt(0); // See if we can stop now (if there's only one item or we're empty, we're done) if (_list.Count > 1) { // Move the last element to the beginning _list.Insert(0, _list[_list.Count - 1]); _list.RemoveAt(_list.Count - 1); // Start reheapify int current = 0, possibleSwap = 0; // Keep going until the tree is a heap while (true) { // Get the positions of the node's children int leftChildPos = 2 * current + 1; int rightChildPos = leftChildPos + 1; // Should we swap with the left child? if (leftChildPos < _list.Count) { // Get the two entries to compare (node and its left child) ChoBinaryHeapEntry entry1 = (ChoBinaryHeapEntry)_list[current]; ChoBinaryHeapEntry entry2 = (ChoBinaryHeapEntry)_list[leftChildPos]; // If the child has a higher key than the parent, set that as a possible swap if (entry2.CompareTo(entry1) > 0) { possibleSwap = leftChildPos; } } else { break; // if can't swap this, we're done } // Should we swap with the right child? Note that now we check with the possible swap // position (which might be current and might be left child). if (rightChildPos < _list.Count) { // Get the two entries to compare (node and its left child) ChoBinaryHeapEntry entry1 = (ChoBinaryHeapEntry)_list[possibleSwap]; ChoBinaryHeapEntry entry2 = (ChoBinaryHeapEntry)_list[rightChildPos]; // If the child has a higher key than the parent, set that as a possible swap if (entry2.CompareTo(entry1) > 0) { possibleSwap = rightChildPos; } } // Now swap current and possible swap if necessary if (current != possibleSwap) { object temp = _list[current]; _list[current] = _list[possibleSwap]; _list[possibleSwap] = temp; } else { break; // if nothing to swap, we're done } // Update current to the location of the swap current = possibleSwap; } } // Return the item from the heap return(toReturn); }