C#实现优先队列和堆排序

C#实现优先队列和堆排序攻略

什么是优先队列?

优先队列(Priority Queue)是在数据结构中使用频率很高的一种类型,它的主要特点是能够在数据插入时将数据进行优先级的排序。

并且每次取出数据时取的是优先级最高的数据。

通常情况下我们使用最大堆来实现优先队列。

最大堆是一种特殊的堆,它的特点是每个结点都大于等于它的子结点。

什么是堆排序?

堆排序是一种排序算法,它通过建立最大堆(或最小堆)来实现排序。排序的过程分两步:第一步是通过建立最大堆,将元素最大的元素交换到第一位(或最小堆元素交换到末位)。第二步是将其余无序元素继续建立最大堆,直到无序的元素只剩最后一个,排序完成。

实现优先队列和堆排序

1. 实现最大堆

最大堆可以用数组来实现。

数组下标从0开始,节点i的左儿子为2i+1,右儿子为2i+2,父节点为(i-1)/2。

class MaxHeap<T> where T : IComparable<T>
{
    private List<T> Heap;

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

    public void Insert(T item)
    {
        Heap.Add(item);
        int n = Heap.Count - 1;
        while (n != 0 && Heap[n].CompareTo(Heap[(n - 1) / 2]) > 0)
        {
            T temp = Heap[n];
            Heap[n] = Heap[(n - 1) / 2];
            Heap[(n - 1) / 2] = temp;
            n = (n - 1) / 2;
        }
    }

    public T RemoveMax()
    {
        int n = Heap.Count - 1;
        T max = Heap[0];
        Heap[0] = Heap[n];
        Heap.RemoveAt(n);
        n--;
        int i = 0, j = 1;
        while (j <= n)
        {
            if (j < n && Heap[j].CompareTo(Heap[j + 1]) < 0)
            {
                j++;
            }
            if (Heap[i].CompareTo(Heap[j]) < 0)
            {
                T temp = Heap[i];
                Heap[i] = Heap[j];
                Heap[j] = temp;
            }
            else
            {
                break;
            }
            i = j;
            j = i * 2 + 1;
        }
        return max;
    }
}

2. 实现优先队列

使用最大堆实现优先队列。

class PriorityQueue<T> where T : IComparable<T>
{
    private MaxHeap<T> Heap;

    public PriorityQueue()
    {
        Heap = new MaxHeap<T>();
    }

    public void Enqueue(T item)
    {
        Heap.Insert(item);
    }

    public T Dequeue()
    {
        return Heap.RemoveMax();
    }
}

3. 实现堆排序

使用前面实现的最大堆实现堆排序。

class HeapSort<T> where T : IComparable<T>
{
    private static void Heapify(List<T> list)
    {
        int n = list.Count - 1;
        int i = (n - 1) / 2;
        while (i >= 0)
        {
            int maxIndex = i;
            int j = i * 2 + 1;
            while (j < n)
            {
                if (j + 1 < n && list[j].CompareTo(list[j + 1]) < 0)
                {
                    j++;
                }
                if (list[maxIndex].CompareTo(list[j]) < 0)
                {
                    maxIndex = j;
                }
                j = j * 2 + 1;
            }
            if (maxIndex != i)
            {
                T temp = list[i];
                list[i] = list[maxIndex];
                list[maxIndex] = temp;
            }
            i--;
        }
    }

    public static List<T> Sort(List<T> list)
    {
        int n = list.Count - 1;
        int i = n;
        while (i > 0)
        {
            T temp = list[0];
            list[0] = list[i];
            list[i] = temp;
            i--;
            Heapify(list.GetRange(0, i + 1));
        }
        return list;
    }
}

4. 示例说明

示例1:使用优先队列实现数组中最小的k个数

public static List<int> GetLeastNumbers(int[] arr, int k)
{
    PriorityQueue<int> pq = new PriorityQueue<int>();
    foreach (int i in arr)
    {
        if (pq.GetCount() < k || i < pq.Peek())
        {
            pq.Enqueue(i);
        }
        if (pq.GetCount() > k)
        {
            pq.Dequeue();
        }
    }
    return pq.GetList();
}

示例2:使用堆排序对数组进行排序

List<int> list = new List<int>() {3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5};
list = HeapSort<int>.Sort(list);
foreach (int i in list)
{
    Console.Write($"{i} ");
}

总结

通过本文的介绍,我们了解了优先队列和堆排序的原理,并通过C#完成了基本的实现。

需要注意的地方是在实现最大堆和堆排序时,数组下标和计算有些不同,需要结合代码仔细理解。除此之外,最大堆和堆排序还有其他更高效、更复杂的实现方式,读者可以自行查阅学习。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#实现优先队列和堆排序 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • java冒泡排序简单实例

    下面我来详细讲解一下“Java冒泡排序简单实例”的完整攻略。 简介 冒泡排序是一种简单的排序算法,它重复地走访过要排序的数列,每次比较相邻的两个元素,如果它们的顺序错误就将它们交换过来。重复上述步骤直到整个数列都有序为止。 实现步骤 首先,我们需要定义一个整型数组,用于存储待排序的数据。 int[] array = {5, 3, 8, 6, 4}; 定义一个…

    算法与数据结构 2023年5月19日
    00
  • 排序算法图解之Java插入排序

    首先要了解什么是插入排序,插入排序是排序算法中简单直观的一种,其原理是将未排序的元素一个一个插入到已经排好序的元素中,最终得到一个有序的序列。那么下面我将用Java代码来演示插入排序的实现过程,并且提供详细的注释帮助读者理解。 算法步骤 从第一个元素开始,认为第一个元素是已经排好序的,取第二个元素和已排序的元素进行比较,如果第二个元素比已排序的元素小,则交换…

    算法与数据结构 2023年5月19日
    00
  • JS前端面试必备——基本排序算法原理与实现方法详解【插入/选择/归并/冒泡/快速排序】

    JS前端面试必备——基本排序算法原理与实现方法详解 在前端面试中,算法是一个必考的考点,掌握一些基本的排序算法对于一个前端工程师来说是非常重要的。 排序算法的分类 排序算法可以按照许多不同的标准进行分类: 平均时间复杂度 空间复杂度 稳定性 内部排序和外部排序 在这篇文章中,我们将按照时间复杂度从小到大的顺序介绍以下五个基本的排序算法:插入排序、选择排序、归…

    算法与数据结构 2023年5月19日
    00
  • c语言冒泡排序法代码

    冒泡排序是常见的排序算法之一,它的基本思想是通过一系列的比较和交换来不断将列表中的最大值或最小值浮到列表的顶部(如冒泡一般),直到整个列表都有序排列。以下是一份c语言版本的冒泡排序代码: void bubbleSort(int arr[], int n){ int i, j; for (i = 0; i < n-1; i++){ for (j = 0;…

    算法与数据结构 2023年5月19日
    00
  • 经典算法:基数排序的小例子

    让我来为你详细讲解“经典算法:基数排序的小例子”的完整攻略。 前言 基数排序是一种常见的排序算法,它的时间复杂度为O(nk),其中n表示待排序元素的个数,k表示元素的最大值的位数。相对于其他排序算法,它的时间复杂度比较低,适合用于对大量数据排序的情况。 算法思想 基数排序的基本思想是:将待排序的元素按照一定规则拆分成多个关键字,然后依次对每个关键字进行排序,…

    算法与数据结构 2023年5月19日
    00
  • c++深入浅出讲解堆排序和堆

    C++深入浅出讲解堆排序和堆 堆的定义 堆是一种特殊的树形数据结构,它满足以下两个特性: 堆是一个完全二叉树(Complete Binary Tree); 堆中每个节点的值都大于等于(或小于等于)其左右子节点的值。 可以看出,堆一般分为两种类型:大根堆(Max Heap)和小根堆(Min Heap)。大根堆的每个节点的值都大于等于其左右子节点的值,小根堆则相…

    算法与数据结构 2023年5月19日
    00
  • C++实现冒泡排序(BubbleSort)

    C++实现冒泡排序(BubbleSort)攻略 冒泡排序是一种简单的排序算法,它会重复地比较相邻的两个元素,如果顺序错误就交换它们的位置,直到排序完成。下面是C++实现冒泡排序的步骤。 1. 理解冒泡排序的基本原理 冒泡排序的基本思路是将待排序的数组分为已排序的部分和未排序的部分,先从未排序的部分开始,进行比较相邻元素的大小,并交换位置,直到本轮最大的元素被…

    算法与数据结构 2023年5月19日
    00
  • 修复IE9&safari 的sort方法

    修复IE9和Safari的sort()方法需要遵循以下步骤: 1. 检查代码 要修复排序方法,首先需要检查代码,找出可能存在的问题。请确保你的代码中使用的是正确的sort()方法,并且没有拼写错误和语法问题。同时,还要检查你的代码能否适用于所有浏览器。 2. 自定义排序方法 当浏览器不支持sort()方法时,我们可以自定义一个排序方法来替代它。我们可以使用J…

    算法与数据结构 2023年5月19日
    00
合作推广
合作推广
分享本页
返回顶部