C#数据结构之最小堆的实现方法

C#数据结构之最小堆的实现方法

什么是最小堆?

最小堆是一种特殊的二叉树结构,它满足以下两个条件:

  1. 是一个完全二叉树。
  2. 任意节点值不大于其子节点的值。

最小堆的根节点是整个堆中最小的元素,而它的左右子节点也必定是整个堆中数值最小的元素。

最小堆的实现

实现最小堆需要用到数组和指针,以下是一个简单的最小堆类。

public class MinHeap<T> where T : IComparable<T>
{
    private T[] _heap;
    private int _size = 0;
    private const int _defaultCapacity = 32;

    public MinHeap()
    {
        _heap = new T[_defaultCapacity];
    }

    public MinHeap(int capacity)
    {
        _heap = new T[capacity];
    }

    public void Insert(T item)
    {
        if (_size == _heap.Length)
        {
            Array.Resize(ref _heap, _heap.Length * 2);
        }

        _heap[_size] = item;
        ShiftUp(_size);
        _size++;
    }

    public T Pop()
    {
        if (_size == 0)
        {
            throw new InvalidOperationException("Heap is empty.");
        }

        var item = _heap[0];
        _size--;
        _heap[0] = _heap[_size];
        _heap[_size] = default(T);
        ShiftDown(0);
        return item;
    }

    private void ShiftUp(int i)
    {
        var parent = (i - 1) / 2;
        while (i > 0 && _heap[i].CompareTo(_heap[parent]) < 0)
        {
            var tmp = _heap[i];
            _heap[i] = _heap[parent];
            _heap[parent] = tmp;
            i = parent;
            parent = (i - 1) / 2;
        }
    }

    private void ShiftDown(int i)
    {
        var left = (i * 2) + 1;
        var right = (i * 2) + 2;
        var smallest = i;

        if (left < _size && _heap[left].CompareTo(_heap[smallest]) < 0)
        {
            smallest = left;
        }

        if (right < _size && _heap[right].CompareTo(_heap[smallest]) < 0)
        {
            smallest = right;
        }

        if (smallest != i)
        {
            var tmp = _heap[i];
            _heap[i] = _heap[smallest];
            _heap[smallest] = tmp;
            ShiftDown(smallest);
        }
    }
}

这个实现拥有两个构造函数,允许你选择初始容量。Insert 和 Pop 方法分别插入和删除元素。ShiftUp 和 ShiftDown 方法分别用于维护堆的性质。

之后,可以像下面这样使用这个类:

var heap = new MinHeap<int>();
heap.Insert(3);
heap.Insert(2);
heap.Insert(1);
Console.WriteLine(heap.Pop()); // 1
Console.WriteLine(heap.Pop()); // 2
Console.WriteLine(heap.Pop()); // 3

示例说明

假设有一个需要维护单一频率数据的应用,为了合理地利用内存占用和计算性能,在频率数据已经被加载到内存中的场景,可以使用最小堆进行排序查找,缩短算法时间。以下是实现场景的粗略思路:

  1. 频率数组顺序扫描到数据,将数据一次加入最小堆;
  2. 堆满后比较堆根节点,删除堆根数据,插入新数据;
  3. 反复执行 2 步骤,最后得到排序完毕的数据,即为单一频率数据。

另一个实现场景可以是,在一个延迟加载的海量数据中,按指定大小分批序列化,存储到单独的文件,最后合并单独大小序列化文件成结果文件。在这个场景中,使用最小堆可以很好地将延迟加载的海量单一数据进行排序,便于分批序列化和合并文件操作,优化磁盘和时间性能。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#数据结构之最小堆的实现方法 - Python技术站

(0)
上一篇 2023年6月7日
下一篇 2023年6月7日

相关文章

  • 利用C#编写一个Windows服务程序的方法详解

    Title: 利用C#编写一个Windows服务程序的方法详解 介绍 Windows服务是在后台运行的程序,可以在计算机启动时自动启动,不需要用户登陆即可运行。本文将详细讲解如何利用C#编写一个Windows服务程序。 步骤 1.创建Windows服务项目 打开Microsoft Visual Studio,选择“新建项目”,在左侧菜单中选择“Visual.…

    C# 2023年6月1日
    00
  • C#如何让winform程序中的输入文本框保留上次的输入

    要让WinForm程序中的输入文本框保留上次的输入,一种比较常见的方法是使用应用程序设置(Application Settings),下面我将提供具体的攻略。 第一步:启用应用程序设置 在Visual Studio中打开你的WinForm项目; 打开项目属性窗口(可以通过在解决方案资源管理器中右键单击项目并选择“属性”或者通过菜单栏的“项目”->“属性…

    C# 2023年6月6日
    00
  • C#通过属性名称获取(读取)属性值的方法

    获取C#对象的属性值通常可以使用对象的属性名称来实现。在 C# 中,属性名称是一个字符串,可以在运行时利用反射机制获取对象的属性信息,并通过属性名称获取属性值。 首先,在 C# 中利用反射机制获取对象的属性信息,可以通过以下步骤来实现: 获取对象的类型信息:使用Type.GetType或typeof关键字获取对象类型信息,例如: csharp Type ty…

    C# 2023年5月31日
    00
  • ASP.NET Core在Linux下为dotnet创建守护进程

    ASP.NET Core在Linux下为dotnet创建守护进程 在Linux下,可以使用systemd来创建守护进程,以确保ASP.NET Core应用程序在系统启动时自动启动,并在崩溃时自动重启。本攻略将提供一些示例,演示如何在Linux下为dotnet创建守护进程。 步骤 步骤1:创建.NET Core Web API项目 首先,需要创建一个.NET …

    C# 2023年5月17日
    00
  • 基础-字符串驻留池

    字符串驻留池(string intern pool)是指,对于某些编程语言,相同的字符串字面值(即具有相同文本内容的字符串)在程序运行时只会被在内存中存储一份,即只保存一个字符串实例。这样做可以减少内存占用,并提高程序执行的效率。 在 Java 中,字符串驻留池是一个存储字符串的缓存,它存储在运行时常量池中。当创建字符串对象时,如果该字符串已经存在于字符串驻…

    C# 2023年5月9日
    00
  • C# 中string.split用法详解

    下面是关于”C#中string.split用法详解”的完整攻略: 1. split方法的作用 split方法是用于将字符串分割成字符串数组的方法。可以使用指定的分隔符对字符串进行拆分,获取到拆分后的各个子字符串。拆分后的子字符串将存储在一个字符串数组中,数组元素的个数就是拆分后子字符串的数量。 2. split方法的语法 下面是split方法的语法: pub…

    C# 2023年6月8日
    00
  • C#实现推送钉钉消息的方法示例

    C#实现推送钉钉消息的方法示例 简介 钉钉作为一款企业通讯解决方案,提供了多种钉钉开放能力,开发者可以通过API对接钉钉实现企业级应用。其中消息推送是企业使用频率较高的功能之一,本文将介绍如何使用C#实现消息推送功能。 步骤 1.注册开放平台 在使用钉钉API前,需要先在钉钉开放平台注册账号并创建应用。如未注册需先进行注册,注册完成后创建应用,获取AppKe…

    C# 2023年5月31日
    00
  • C#实现泛型List分组输出元素的方法

    下面是详细讲解“C#实现泛型List分组输出元素的方法”的完整攻略。 1. 题目背景 在 C# 中, 泛型(Generic)是指写代码时不必指定具体的类型,而是在使用时在指定类型。List 是 C# 中常用的泛型集合类型。当我们需要对一个 List 进行分组后输出元素,就需要用到泛型 List 分组的方法。 2. 泛型 List 分组的方法 2.1 Grou…

    C# 2023年6月7日
    00
合作推广
合作推广
分享本页
返回顶部