问题描述
欢迎大家。
我了解队列的原理,我自己已经实现了。
我需要用一个函数来补充代码,以在当前存在的元素中找到最小的元素。该代码中的某些要点不是我一个人完成的,原则上,我只是开始进行面向对象的编程。
给我一个关于如何引用元素以及用于查找最小元素的循环的想法。
谢谢。
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",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
}
}
解决方法
假设我们将这些值放入队列:
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
列表为例(因为它恰好是最长/最有趣的),并查看出队情况:
index: 0 1 2 3 4 5 6 7 8
dequeue: 5 3 8 4 2 1 6 3 7
minimum: [1,7] [3,7] [7] []
请注意,我们在出列相同值时只是从列表中删除了最小值。
现在,我们需要的是一个数据结构,该数据结构使我们可以检查第一个元素(在O(1)
内),删除第一个元素(在O(1)
内)并向其中添加新值结束(这也需要从末尾删除摊销的O(n)
元素)。
由于这是一次大学练习,因此我将实际的实现留给您,但这有望将您推向正确的方向。