< Summary

Class:Itinero.Routing.DataStructures.BinaryHeap`1
Assembly:Itinero
File(s):/home/runner/work/routing2/routing2/src/Itinero/Routing/DataStructures/BinaryHeap.cs
Covered lines:67
Uncovered lines:14
Coverable lines:81
Total lines:161
Line coverage:82.7% (67 of 81)
Covered branches:15
Total branches:18
Branch coverage:83.3% (15 of 18)
Tag:263_26948838820

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
.ctor()100%1100%
.ctor(...)100%1100%
get_Count()100%1100%
Push(...)83.33%686.36%
PeekWeight()100%10%
Peek()100%10%
Pop(...)83.33%1287.8%
Clear()100%1100%

File(s)

/home/runner/work/routing2/routing2/src/Itinero/Routing/DataStructures/BinaryHeap.cs

#LineLine coverage
 1using System;
 2
 3namespace Itinero.Routing.DataStructures;
 4
 5/// <summary>
 6/// Implements a priority queue in the form of a binary heap.
 7/// </summary>
 8internal class BinaryHeap<T>
 9    where T : struct
 10{
 11    private (T item, double priority)[] _data;
 12    private int _count;
 13    private uint _latestIndex;
 14
 15    /// <summary>
 16    /// Creates a new binary heap.
 17    /// </summary>
 18    public BinaryHeap()
 3517519        : this(1024) { }
 20
 21    /// <summary>
 22    /// Creates a new binary heap.
 23    /// </summary>
 1172524    public BinaryHeap(uint initialSize)
 1172525    {
 1172526        _data = new (T, double)[initialSize];
 1172527        _count = 0;
 1172528        _latestIndex = 1;
 1172529    }
 30
 31    /// <summary>
 32    /// Returns the number of items in this queue.
 33    /// </summary>
 40792934    public int Count => _count;
 35
 36    /// <summary>
 37    /// Enqueues a given item.
 38    /// </summary>
 39    public void Push(T item, double priority)
 41441240    {
 41441241        _count++;
 42
 41441243        if (_latestIndex == _data.Length - 1)
 044        {
 045            Array.Resize(ref _data, _data.Length * 2);
 046        }
 47
 48        // add the item at the first free point.
 41441249        _data[_latestIndex] = (item, priority);
 50
 51        // ... and let it 'bubble' up using hole-sinking:
 52        // instead of swapping at each level, leave a hole and move it up.
 41441253        var bubbleIndex = _latestIndex;
 41441254        _latestIndex++;
 69314655        while (bubbleIndex != 1)
 62365056        {
 62365057            var parentIdx = bubbleIndex / 2;
 62365058            if (priority < _data[parentIdx].priority)
 27873459            {
 27873460                _data[bubbleIndex] = _data[parentIdx];
 27873461                bubbleIndex = parentIdx;
 27873462            }
 63            else
 34491664            {
 34491665                break;
 66            }
 27873467        }
 68
 41441269        _data[bubbleIndex] = (item, priority);
 41441270    }
 71
 72    /// <summary>
 73    /// Returns the smallest weight in the queue.
 74    /// </summary>
 75    public double PeekWeight()
 076    {
 077        return _data[1].priority;
 078    }
 79
 80    /// <summary>
 81    /// Returns the object with the smallest weight.
 82    /// </summary>
 83    public T Peek()
 084    {
 085        return _data[1].item;
 086    }
 87
 88    /// <summary>
 89    /// Returns the object with the smallest weight and removes it.
 90    /// </summary>
 91    public T Pop(out double priority)
 39795792    {
 39795793        priority = 0;
 39795794        if (_count <= 0)
 095        {
 096            return default;
 97        }
 98
 39795799        var result = _data[1];
 397957100        priority = result.priority;
 101
 397957102        _count--;
 397957103        _latestIndex--;
 104
 105        // take the last element and sift it down from the root.
 397957106        var last = _data[_latestIndex];
 397957107        var lastPriority = last.priority;
 108
 109        // sift down using hole-sinking: move the smaller child up,
 110        // place the last element at the final hole position.
 397957111        uint hole = 1;
 1210591112        while (true)
 1210591113        {
 1210591114            var child = hole * 2;
 1210591115            if (child + 1 <= _latestIndex)
 916357116            {
 117                // two children exist — pick the smaller one.
 916357118                if (_data[child + 1].priority < _data[child].priority)
 422955119                {
 422955120                    child++;
 422955121                }
 122
 916357123                if (lastPriority <= _data[child].priority)
 103723124                {
 103723125                    break;
 126                }
 127
 812634128                _data[hole] = _data[child];
 812634129                hole = child;
 812634130            }
 294234131            else if (child <= _latestIndex)
 98488132            {
 133                // only left child exists.
 98488134                if (lastPriority <= _data[child].priority)
 98488135                {
 98488136                    break;
 137                }
 138
 0139                _data[hole] = _data[child];
 0140                hole = child;
 0141            }
 142            else
 195746143            {
 195746144                break;
 145            }
 812634146        }
 147
 397957148        _data[hole] = last;
 149
 397957150        return result.item;
 397957151    }
 152
 153    /// <summary>
 154    /// Clears this priority queue.
 155    /// </summary>
 156    public void Clear()
 11725157    {
 11725158        _count = 0;
 11725159        _latestIndex = 1;
 11725160    }
 161}