C#最小堆实现

最近看了《算法》第四版这本书,里边关于优先队列讲的确实非常好,之前自己写过的最小堆代码过于臃肿了,这次重构一下,记录发上来

public class Heap<T> where T : IComparable<T>
{
    readonly List<T> m_heap;

    public int Count => m_heap.Count - 1;

    public Heap()
    {
        m_heap = new List<T>{ default };
    }

    private void Swim(int pos)
    {
        while (pos > 1 && m_heap[pos].CompareTo(m_heap[pos >> 1]) < 0)
        {
            Swap(m_heap, pos, pos >> 1);
            pos >>= 1;
        }
    }

    private void Sink(int pos)
    {
        while (pos << 1 <= m_heap.Count - 1)
        {
            int j = pos << 1;
            if (j < m_heap.Count - 1 && m_heap[j].CompareTo(m_heap[j + 1]) > 0) j++;
            if (m_heap[pos].CompareTo(m_heap[j]) <= 0) break;
            Swap(m_heap, pos, j);
            pos = j;
        }
    }

    public void Insert(T value)
    {
        m_heap.Add(value);
        Swim(m_heap.Count - 1);
    }

    public T Remove()
    {
        T res = m_heap[1];
        Swap(m_heap, 1, m_heap.Count - 1);
        m_heap.RemoveAt(m_heap.Count - 1);
        Sink(1);
        return res;
    }

    public T Peek()
    {
        return m_heap[1];
    }

    private static void Swap(List<T> list, int a, int b)
    {
        T temp = list[a];
        list[a] = list[b];
        list[b] = temp;
    }
}

主要就是Swim和Sink,提取了Swap函数以后,代码会大幅度简洁并简短。

这个后序有缘还会再优化,内存管理这块还不是特别清晰明了

 

之前第一版的序号计算有些问题,重新上传一版

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
无序数组堆化通常指的是将一个无序的数组转换成最大堆或最小堆的过程。堆是一种特殊的树形数据结构,可以高效地维护一组元素的最大值(对于最大堆)或最小值(对于最小堆)。在实际应用中,堆常用于优先队列、排序算法等。 ### 最大堆的基本性质: 1. **完全二叉树**:所有层都被充分填充,最后一层从左到右按顺序排列; 2. **堆化属性**:每个节点的值大于等于其子节点的值,根节点拥有最大值。 ### C# 实现无序数组转最大堆的例子: 首先,定义一个辅助函数 `Heapify` 来修复某个位置的子树使其满足堆性质: ```csharp private void Heapify(int[] arr, int index, int heapSize) { int largest = index; // 初始化当前节点为最大 int leftChild = (index * 2) + 1; int rightChild = (index * 2) + 2; // 检查左子节点是否存在,并且左子节点是否比当前节点更大 if (leftChild < heapSize && arr[leftChild] > arr[largest]) largest = leftChild; // 检查右子节点是否存在,并且右子节点是否比当前节点或左子节点更大 if (rightChild < heapSize && arr[rightChild] > arr[largest]) largest = rightChild; // 如果最大的节点不是当前节点,则交换它们的位置,并继续向下调整 if (largest != index) { (arr[index], arr[largest]) = (arr[largest], arr[index]); Heapify(arr, largest, heapSize); } } ``` 接下来,实现主函数 `BuildMaxHeap` 来构建最大堆: ```csharp public static void BuildMaxHeap(int[] arr) { int n = arr.Length; for (int i = n / 2 - 1; i >= 0; i--) { Heapify(arr, i, n); } } ``` 最后,验证函数和示例: ```csharp class Program { static void Main(string[] args) { int[] array = { 4, 10, 3, 5, 1 }; Console.WriteLine("原始数组:"); foreach (var item in array) Console.Write(item + " "); BuildMaxHeap(array); Console.WriteLine("\n最大堆化的数组:"); foreach (var item in array) Console.Write(item + " "); } private static void BuildMaxHeap(int[] arr) { BuildMaxHeapHelper(arr); } // 这里假设有一个私有的辅助函数 BuildMaxHeapHelper 来简化堆化的实现逻辑 } // 注意:以上代码需要配合适当的初始化和测试点,这里仅提供了一个基本框架。 ``` ### 相关问题: 1. **如何判断一个数组是否已经是一个堆?** 答案包括检查数组是否满足堆的性质,即所有节点都小于(对于最大堆)或大于(对于最小堆)其子节点。 2. **最大堆与最小堆的区别是什么?** 最大堆保证根节点总是包含堆内最大值;相反,最小堆则保证根节点包含最小值。 3. **为什么在排序算法(如堆排序)中使用堆?** 使用堆排序是因为堆操作能高效地找到最大或最小元素,通过反复调整堆实现排序过程,使得算法时间复杂度保持在O(n log n),适用于大数据集的排序任务。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值