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日

相关文章

  • JavaScript中几种排序算法的简单实现

    JavaScript中几种排序算法的简单实现 排序算法在计算机科学中是一个基本问题。不同的排序算法具有不同的时间和空间复杂度,选择合适的排序算法可以提高程序的效率。本文介绍了JavaScript中几种排序算法的简单实现,包括冒泡排序、选择排序、插入排序、归并排序和快速排序。 冒泡排序 冒泡排序是最简单的排序算法之一。它重复遍历列表,比较相邻的元素,并交换它们…

    算法与数据结构 2023年5月19日
    00
  • c语言排序之归并排序(递归和非递归)

    下面我来为你详细讲解“C语言排序之归并排序(递归和非递归)”的完整攻略: 什么是归并排序 归并排序是一种基于分治策略的排序算法,其基本思想是将原始数据分成若干个小的子序列,然后将这些小的子序列两两合并成为较大的子序列,直到最终合并成为完整的有序序列。 归并排序可以采用递归和非递归两种方式实现。 归并排序递归实现 归并排序的递归实现相对容易理解,可以通过以下步…

    算法与数据结构 2023年5月19日
    00
  • Go语言实现常用排序算法的示例代码

    本文将详细介绍如何使用Go语言实现常用排序算法的示例代码。主要内容包括: 排序算法介绍 排序算法示例代码 算法测试 排序算法介绍 排序算法是计算机科学基本的算法,其目的是将一组数据按照特定的规则进行排序。常用的排序算法包括冒泡排序、选择排序、插入排序、归并排序和快速排序等。以下是每种算法的简单介绍: 冒泡排序:重复比较相邻的两个元素,将较大的元素向后移动,最…

    算法与数据结构 2023年5月19日
    00
  • JS中数组随机排序实现方法(原地算法sort/shuffle算法)

    JS中实现数组随机排序有两种常见方法:原地随机排序算法和使用shuffle算法。 原地随机排序算法 原地随机排序算法(in-place shuffle algorithm)是将数组中元素随机地乱序,同时保持每个元素之间的相对位置不变。算法的时间复杂度是O(n),空间复杂度是O(1),因为所有的操作都是在原数组上进行。 实现步骤 获取数组长度 从数组的最后一个…

    算法与数据结构 2023年5月19日
    00
  • c语言快速排序算法示例代码分享

    首先,我们需要了解什么是快速排序。快速排序(QuickSort)是一种排序算法,其采用了分治的思想,并使用递归的方式处理数据集合。它的基本思想是从待排序的数据集合中选择一个元素作为分界点(一般称为pivot),然后将小于pivot的元素放到pivot左边,大于pivot的元素放到pivot右边,最后将pivot放到中间位置。然后递归处理pivot左右两边的子…

    算法与数据结构 2023年5月19日
    00
  • redis zset实现滑动窗口限流的代码

    Redis ZSET(有序集合)非常适合实现滑动窗口限流。下面是实现滑动窗口限流的Redis ZSET代码攻略: 步骤一:定义一个键和窗口大小 为了使用Redis ZSET实现滑动窗口限流,您需要为每个限流器定义一个键。键的值将存储在Redis Sorted Set中,并且每个元素将具有其分数。我们将使用时间戳作为分数。此外,需要指定每个限制限流器的窗口大小…

    算法与数据结构 2023年5月19日
    00
  • C语言中的结构体快排算法

    C语言中的结构体快排算法 在C语言中,复杂的数据类型可以通过结构体定义。结构体是一种自定义类型,可以由不同类型的变量组成。快速排序算法是一种高效的排序算法,通过十分巧妙的算法思想,可以在平均$O(nlogn)$的时间复杂度内完成数组的排序。对于结构体类型的排序,在快速排序算法中也可以使用。本文主要讲解如何在C语言中使用结构体进行快排排序。 快速排序算法 快速…

    算法与数据结构 2023年5月19日
    00
  • Js Snowflake(雪花算法)生成随机ID的实现方法

    Js Snowflake(雪花算法)生成随机ID的实现方法 介绍 雪花算法是Twitter开源的一种简单高效、生成唯一ID的算法,可以用于解决数据分布式系统中的ID生成器。本文将介绍使用Js实现雪花算法生成随机ID的完整方法。 实现 引入 首先,我们需要引入雪花算法的js库文件snowflake.js,并在页面中引入 <script src=&quot…

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