在“队列”结构中添加查找最小元素的功能
Posted
技术标签:
【中文标题】在“队列”结构中添加查找最小元素的功能【英文标题】:Add the function of finding the minimum element to the "Queue" structure 【发布时间】:2021-02-03 03:03:28 【问题描述】:欢迎大家。了解队列的原理,自己实现了。 我需要用一个函数来补充代码,以在当前存在的元素中找到最小的元素。这段代码中的一些点不是我自己做的,原则上我只是开始接触面向对象的编程。 告诉我如何引用元素以及使用哪个循环来查找最小元素。 谢谢。
class Program
public static void Main()
var watch = new Stopwatch();
watch.Start(); // начало замера времени
long before = GC.GetTotalMemory(false);
int min = int.MaxValue;
Queue queue = new Queue(); // Структура очередь
File.WriteAllText(@"output.txt", string.Empty);
using (StreamReader sr = new StreamReader(@"input.txt", System.Text.Encoding.Default)) // Считывание файла input.txt
string line;
while ((line = sr.ReadLine()) != null) // пока строки в файле не null
if (line[0] == '+') // если "+", добавить элемент со значением, стоящим после "+"
var pattern = new Regex(@"\d+");
var numberStr = pattern.Match(line).Groups[0].Value;
queue.Enqueue(int.Parse(numberStr));
if (line[0] == '-') // если "-", выпустить элемент из очереди (first in - first out)
using (StreamWriter sw = new StreamWriter(@"output.txt", true, System.Text.Encoding.Default))
sw.WriteLine(queue.Dequeue());
if (line[0] == '?') // если "?", вывести наименьший элемент в очереди
using (StreamWriter sw = new StreamWriter(@"output.txt", true, System.Text.Encoding.Default))
sw.WriteLine(queue.Minimum());
long after = GC.GetTotalMemory(false);
long consumedInMegabytes = (after - before) / (1024); // замер памяти в КБ
Console.WriteLine($"Затраты памяти (КБ): consumedInMegabytes");
watch.Stop(); // конец замера времени
Console.WriteLine($"Время выполнения (миллисекунд): watch.ElapsedMilliseconds");
public class QueueItem
public int Value get; set;
public QueueItem Next get; set;
public class Queue
QueueItem head;
QueueItem tail;
public void Enqueue(int value) // функция добавления элемента в очередь
if (head == null)
tail = head = new QueueItem Value = value, Next = null ;
else
var item = new QueueItem Value = value, Next = null ;
tail.Next = item;
tail = item;
public int Dequeue() // функция удаления элемента из очереди
if (head == null) throw new InvalidOperationException();
var result = head.Value;
head = head.Next;
if (head == null)
tail = null;
return result;
public int Minimum()
// WHAT I NEED DO
【问题讨论】:
顺便说一下,最小元素的输出顺序必须和从文档中读取的顺序一致 不知道这是否只是为了玩,但Stopwatch
不是基准测试工具。
另外:如果你用英文注释你的代码,你会大大增加能够阅读它们的人数;)
“请告诉我如何引用元素以及使用哪个循环来查找最小元素”。您基本上有两个选择:通过在 Dequeue / Enqueue 上更新它或每次迭代完整队列来跟踪 min Value。两者都有明显的优缺点。
对这个问题的主要观察是,一旦你将一个值x
排入队列,所有早先排入队列的值y
和y > x
变得无关紧要。这应该允许您保留第二个队列,该队列在O(1)
时间处理Minimum()
和Dequeue
,在摊销O(n)
时间处理Enqueue
。
【参考方案1】:
假设我们将这些值排入队列:
index: 0 1 2 3 4 5 6 7 8 9
value: 5 3 8 4 2 1 6 3 7 2
第 3 项入队后,Minimum
的正确值是多少?这得看情况。它可以是 3
(如果项目 1 尚未出队),也可以是 4
。但它永远不可能是5
或8
,因为4 < 5
和4 < 8
,无论哪个值已经出队。
所以我们可以在每次入队后构建一个具有Minimum
潜在答案的数据结构:
index: 0 1 2 3 4 5 6 7 8 9
value: 5 3 8 4 2 1 6 3 7 2
minimum: [5] [3] [3, 8] [3, 4] [2] [1] [1, 6] [1, 3] [1, 3, 7] [1, 2]
看到minimum
列表总是排序的。如果我们遇到一个大于列表中最大项目的新值,我们会追加它。如果它更小,我们将所有更大的值替换为新值。
现在,出队会发生什么?让我们取索引 8 之后的 minimum
列表(因为它恰好是最长/最有趣的),看看 dequeue 会发生什么:
index: 0 1 2 3 4 5 6 7 8
dequeue: 5 3 8 4 2 1 6 3 7
minimum: [1, 3, 7] [1, 3, 7] [1, 3, 7] [1, 3, 7] [1, 3, 7] [3, 7] [3, 7] [7] []
请注意,当我们将相同的值出列时,我们只是从列表中删除了最小值。
现在我们需要的是一个数据结构,它允许我们检查第一个元素(O(1)
时间),删除第一个元素(O(1)
时间),并在末尾添加一个新值(这需要也从末尾删除摊销的O(n)
元素)。
由于这是一个大学练习,我将把实际的实现留给你,但这应该会推动你朝着正确的方向前进。
【讨论】:
以上是关于在“队列”结构中添加查找最小元素的功能的主要内容,如果未能解决你的问题,请参考以下文章