C#最优队列最小堆小顶堆大顶堆小根堆大根堆PriorityQueue的使用

本文主要是介绍C#最优队列最小堆小顶堆大顶堆小根堆大根堆PriorityQueue的使用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最优队列有多种叫法,什么小根堆,大根堆,小顶堆,大顶堆。

队列分多种,线性队列(简单队列),循环队列,最优队列等等。

最优队列,可以看作堆叠箱子,越小的越在上面,或者最大的越在上面。目的就是求出前面最值。比如最大的前3个,或最小的前3个。

framework中只能自己创建类,或者变通由sortedset等来做,现在.net6及以后有了。

下面由.net8(反正它也长期被支持了,就用它吧)。

PriorityQueue定义时要指明两个,前者是元素(对象),后者是优先级,一般是整型,如果是自定义类型,需要对这个优先级自己再定义一个比较器,以便最优队列根据这个比较得知哪个“最优”(最大或最小)。

下面创建多个结构体变量,用大量的数来入队,选取前4个(根据结构体的成员value)。

由于选4个前4个最大值,因此我们设置5为最大容量。满4后就要开始考虑出队问题。

第一种:   满4后,是先判断顶点后入队,还是直接入队出队,这两者哪个效率更优?简单测试一下:

    public struct RecSample{public int Name { get; set; }public int Value { get; set; }}//public class RecCompare : IComparer<RecSample>//{//    public int Compare(RecSample x, RecSample y)//    {//        return x.Value.CompareTo(y.Value);//    }//}internal class Program{private static void Main(string[] args){Random r = new Random();List<RecSample> list = new List<RecSample>();for (int i = 0; i < 30; i++){list.Add(new RecSample { Name = r.Next(0, 30), Value = r.Next(0, 30) });}// 先判断后入队PriorityQueue<RecSample, int> pq1 = new PriorityQueue<RecSample, int>();Stopwatch sw = Stopwatch.StartNew();for (int i = 0; i < 30000000; i++){foreach (var item in list){if (pq1.Count < 5)pq1.Enqueue(item, item.Value);else if (item.Value > pq1.Peek().Value)pq1.EnqueueDequeue(item, item.Value);}}sw.Stop();Console.WriteLine("先判断后入队耗时:" + sw.ElapsedMilliseconds);// 直接入队再出队PriorityQueue<RecSample, int> pq2 = new PriorityQueue<RecSample, int>();sw.Restart();for (int i = 0; i < 30000000; i++){foreach (var item in list){if (pq2.Count < 5)pq2.Enqueue(item, item.Value);elsepq2.EnqueueDequeue(item, item.Value);}}sw.Stop();Console.WriteLine("直接入队再出队耗时:" + sw.ElapsedMilliseconds);Console.ReadKey();}}

多次结果都是后者更优。看来是杞人忧天,不需要再去什么顶点判断,直接入队出队。

第二种:平常我们都是入队出队分成两步使用,比如queue<T>,出队Dequeue,入队Enqueue。现在PriorityQueue里面把两者结合合并,要么直接入队出队DequeueEnqueue,要会出队入队EnqueueDequeue。

现在简单测试分两步,与两步结合的情况:

    public struct RecSample{public int Name { get; set; }public int Value { get; set; }}//public class RecCompare : IComparer<RecSample>//{//    public int Compare(RecSample x, RecSample y)//    {//        return x.Value.CompareTo(y.Value);//    }//}internal class Program{private static void Main(string[] args){Random r = new Random();List<RecSample> list = new List<RecSample>();for (int i = 0; i < 30; i++){list.Add(new RecSample { Name = r.Next(0, 30), Value = r.Next(0, 30) });}// 先判断后入队PriorityQueue<RecSample, int> pq1 = new PriorityQueue<RecSample, int>();Stopwatch sw = Stopwatch.StartNew();for (int i = 0; i < 30000000; i++){foreach (var item in list){if (pq1.Count < 5){pq1.Enqueue(item, item.Value);}else{pq1.Enqueue(item, item.Value);pq1.Dequeue();}}}sw.Stop();Console.WriteLine("先判断后入队耗时:" + sw.ElapsedMilliseconds);// 直接入队再出队PriorityQueue<RecSample, int> pq2 = new PriorityQueue<RecSample, int>();sw.Restart();for (int i = 0; i < 30000000; i++){foreach (var item in list){if (pq2.Count < 5)pq2.Enqueue(item, item.Value);elsepq2.EnqueueDequeue(item, item.Value);}}sw.Stop();Console.WriteLine("直接入队再出队耗时:" + sw.ElapsedMilliseconds);Console.ReadKey();}}

结果是分两步还费时,结合效率更高。

下面截图就没有修改提示语了,自已结合代码看看吧。

结论:不用想当然,微软已经考虑了方方面面,所以直接使用吧,它既然有结合的,还有所考虑的,有时当傻瓜也是一种福气。

这篇关于C#最优队列最小堆小顶堆大顶堆小根堆大根堆PriorityQueue的使用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


原文地址:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.chinasem.cn/article/739675

相关文章

Linux中的计划任务(crontab)使用方式

《Linux中的计划任务(crontab)使用方式》:本文主要介绍Linux中的计划任务(crontab)使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、前言1、linux的起源与发展2、什么是计划任务(crontab)二、crontab基础1、cro

kotlin中const 和val的区别及使用场景分析

《kotlin中const和val的区别及使用场景分析》在Kotlin中,const和val都是用来声明常量的,但它们的使用场景和功能有所不同,下面给大家介绍kotlin中const和val的区别,... 目录kotlin中const 和val的区别1. val:2. const:二 代码示例1 Java

C++变换迭代器使用方法小结

《C++变换迭代器使用方法小结》本文主要介绍了C++变换迭代器使用方法小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录1、源码2、代码解析代码解析:transform_iterator1. transform_iterat

C++中std::distance使用方法示例

《C++中std::distance使用方法示例》std::distance是C++标准库中的一个函数,用于计算两个迭代器之间的距离,本文主要介绍了C++中std::distance使用方法示例,具... 目录语法使用方式解释示例输出:其他说明:总结std::distance&n编程bsp;是 C++ 标准

vue使用docxtemplater导出word

《vue使用docxtemplater导出word》docxtemplater是一种邮件合并工具,以编程方式使用并处理条件、循环,并且可以扩展以插入任何内容,下面我们来看看如何使用docxtempl... 目录docxtemplatervue使用docxtemplater导出word安装常用语法 封装导出方

Linux换行符的使用方法详解

《Linux换行符的使用方法详解》本文介绍了Linux中常用的换行符LF及其在文件中的表示,展示了如何使用sed命令替换换行符,并列举了与换行符处理相关的Linux命令,通过代码讲解的非常详细,需要的... 目录简介检测文件中的换行符使用 cat -A 查看换行符使用 od -c 检查字符换行符格式转换将

使用Jackson进行JSON生成与解析的新手指南

《使用Jackson进行JSON生成与解析的新手指南》这篇文章主要为大家详细介绍了如何使用Jackson进行JSON生成与解析处理,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 核心依赖2. 基础用法2.1 对象转 jsON(序列化)2.2 JSON 转对象(反序列化)3.

使用Python实现快速搭建本地HTTP服务器

《使用Python实现快速搭建本地HTTP服务器》:本文主要介绍如何使用Python快速搭建本地HTTP服务器,轻松实现一键HTTP文件共享,同时结合二维码技术,让访问更简单,感兴趣的小伙伴可以了... 目录1. 概述2. 快速搭建 HTTP 文件共享服务2.1 核心思路2.2 代码实现2.3 代码解读3.

Elasticsearch 在 Java 中的使用教程

《Elasticsearch在Java中的使用教程》Elasticsearch是一个分布式搜索和分析引擎,基于ApacheLucene构建,能够实现实时数据的存储、搜索、和分析,它广泛应用于全文... 目录1. Elasticsearch 简介2. 环境准备2.1 安装 Elasticsearch2.2 J

使用C#代码在PDF文档中添加、删除和替换图片

《使用C#代码在PDF文档中添加、删除和替换图片》在当今数字化文档处理场景中,动态操作PDF文档中的图像已成为企业级应用开发的核心需求之一,本文将介绍如何在.NET平台使用C#代码在PDF文档中添加、... 目录引言用C#添加图片到PDF文档用C#删除PDF文档中的图片用C#替换PDF文档中的图片引言在当