Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions PriorityQueue/PriorityQueue.Tests/GenericPriorityQueueTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
namespace PriorityQueue.Tests;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Надо ещё шапку с информацией о лицензии


public abstract class GenericPriorityQueueTests<TElement, TPriority>
{
private PriorityQueue<TElement, TPriority> queue;

public virtual IComparer<TPriority>? Comparer { get; }

public abstract ItemPair SingleTestPair { get; }

public abstract IEnumerable<ItemPair> SamePriorityTestPairs { get; }

public abstract IEnumerable<ItemPair> IncreasingPriorityTestPairs { get; }

[SetUp]
public void Setup()
{
queue = Comparer == null ? new() : new(Comparer);
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Активнее используйте expression-bodied-методы


[Test]
public void Empty_ShouldBeTrue_ForEmptyQueue()
{
Assert.That(queue.Empty, Is.True);
}

[Test]
public void Empty_ShouldBeFalse_ForNonEmptyQueue()
{
queue.Enqueue(SingleTestPair.Element, SingleTestPair.Priority);
Assert.That(queue.Empty, Is.False);
}

[Test]
public void Dequeue_ShouldThrow_IfQueueIsEmpty()
{
Assert.Throws<InvalidOperationException>(() => queue.Dequeue());
}

[Test]
public void Dequeue_ShouldReturn_EnqueuedItem()
{
queue.Enqueue(SingleTestPair.Element, SingleTestPair.Priority);
Assert.That(queue.Dequeue(), Is.EqualTo(SingleTestPair.Element));
}

[Test]
public void Dequeue_ShouldReturn_EnqueuedItems_InSameOrder_IfPriorityIsSame()
{
foreach (var (element, priority) in SamePriorityTestPairs)
{
queue.Enqueue(element, priority);
}

foreach (var (element, priority) in SamePriorityTestPairs)
{
Assert.That(queue.Dequeue(), Is.EqualTo(element));
}
}

[Test]
public void Dequeue_ShouldReturn_EnqueuedItems_InReverseOrder_IfPriorityIsDecreasing()
{
foreach (var (element, priority) in IncreasingPriorityTestPairs.Reverse())
{
queue.Enqueue(element, priority);
}

foreach (var (element, priority) in IncreasingPriorityTestPairs)
{
Assert.That(queue.Dequeue(), Is.EqualTo(element));
}
}

public readonly record struct ItemPair(TElement Element, TPriority Priority);
}
8 changes: 8 additions & 0 deletions PriorityQueue/PriorityQueue.Tests/GlobalSuppressions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// This file is used by Code Analysis to maintain SuppressMessage
// attributes that are applied to this project.
// Project-level suppressions either have no target or are given
// a specific target and scoped to a namespace, type, member, etc.

using System.Diagnostics.CodeAnalysis;

[assembly: SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1600:Elements should be documented", Justification = "This is project with tests")]
27 changes: 27 additions & 0 deletions PriorityQueue/PriorityQueue.Tests/PriorityQueue.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<LangVersion>latest</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
<PackageReference Include="NUnit" Version="4.2.2" />
<PackageReference Include="NUnit.Analyzers" Version="4.4.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
</ItemGroup>

<ItemGroup>
<Using Include="NUnit.Framework" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="../PriorityQueue/PriorityQueue.csproj" />
</ItemGroup>

</Project>
32 changes: 32 additions & 0 deletions PriorityQueue/PriorityQueue.Tests/TypedPriorityQueueTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
namespace PriorityQueue.Tests;

public static class TypedPriorityQueueTests
{
public class IntPriorityQueue : GenericPriorityQueueTests<int, int>
{
public override ItemPair SingleTestPair => new(123, 456);

public override IEnumerable<ItemPair> SamePriorityTestPairs => Enumerable.Range(1, 64).Select(x => new ItemPair(x, 123));

public override IEnumerable<ItemPair> IncreasingPriorityTestPairs => Enumerable.Range(1, 64).Select(x => new ItemPair(x, x));
}

public class StringPriorityQueue : GenericPriorityQueueTests<string, string>
{
public override IComparer<string>? Comparer { get; } = new NumberStringComparer();

public override ItemPair SingleTestPair => new("1234", "4444");

public override IEnumerable<ItemPair> SamePriorityTestPairs => Enumerable.Range(1, 64)
.Select(x => x.ToString().PadLeft(3, '0')).Select(x => new ItemPair(x, x));

public override IEnumerable<ItemPair> IncreasingPriorityTestPairs => Enumerable.Range(1, 8)
.Select(x => new string('1', x)).Select(x => new ItemPair(x, x));

private class NumberStringComparer : IComparer<string>
{
public int Compare(string? x, string? y)
=> int.Parse(x ?? "0") - int.Parse(y ?? "0");
}
}
}
28 changes: 28 additions & 0 deletions PriorityQueue/PriorityQueue.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PriorityQueue", "PriorityQueue\PriorityQueue.csproj", "{DACEF6B2-BF52-446A-B201-C0D652F8A1FC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PriorityQueue.Tests", "PriorityQueue.Tests\PriorityQueue.Tests.csproj", "{072C7A26-3045-4432-B398-4AC1353DF895}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{DACEF6B2-BF52-446A-B201-C0D652F8A1FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DACEF6B2-BF52-446A-B201-C0D652F8A1FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DACEF6B2-BF52-446A-B201-C0D652F8A1FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DACEF6B2-BF52-446A-B201-C0D652F8A1FC}.Release|Any CPU.Build.0 = Release|Any CPU
{072C7A26-3045-4432-B398-4AC1353DF895}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{072C7A26-3045-4432-B398-4AC1353DF895}.Debug|Any CPU.Build.0 = Debug|Any CPU
{072C7A26-3045-4432-B398-4AC1353DF895}.Release|Any CPU.ActiveCfg = Release|Any CPU
{072C7A26-3045-4432-B398-4AC1353DF895}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
91 changes: 91 additions & 0 deletions PriorityQueue/PriorityQueue/PriorityQueue.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
namespace PriorityQueue;

/// <summary>
/// Prioirty queue data structure.
/// </summary>
/// <typeparam name="TElement">Type of elements.</typeparam>
/// <typeparam name="TPriority">Type of priority associated with each element.</typeparam>
public class PriorityQueue<TElement, TPriority>
{
private IComparer<TPriority> comparer;
private Item? head;

/// <summary>
/// Initializes a new instance of the <see cref="PriorityQueue{TValue, TPriority}"/> class.
/// </summary>
/// <param name="comparer">Comparer to use; if <see langword="null"/>, defaults to <see cref="Comparer{TPriority}.Default"/>.</param>
public PriorityQueue(IComparer<TPriority>? comparer = null)
{
head = null;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Да оно и так null, явной инициализации в конструкторе не требуется (это же не C++)

this.comparer = comparer ?? Comparer<TPriority>.Default;
}

/// <summary>
/// Initializes a new instance of the <see cref="PriorityQueue{TValue, TPriority}"/> class.
/// </summary>
public PriorityQueue()
: this(null)
{
}

/// <summary>
/// Gets a value indicating whether queue is empty.
/// </summary>
public bool Empty => head == null;

/// <summary>
/// Enqueues element into the queue.
/// </summary>
/// <param name="element">Element to enqueue.</param>
/// <param name="priority">Priority of the <paramref name="element"/>.</param>
public void Enqueue(TElement element, TPriority priority)
{
var item = head;
if (item == null)
{
item = new(element, priority, null);
head = item;
return;
}

if (comparer.Compare(priority, item.Priority) < 0)
{
var newHead = new Item(element, priority, item);
head = newHead;
return;
}

while (item.Next != null && comparer.Compare(priority, item.Next.Priority) >= 0)
{
item = item.Next;
}

var newItem = new Item(element, priority, item.Next);
item.Next = newItem;
}

/// <summary>
/// Dequeues element with the least priority from the queue.
/// </summary>
/// <returns>Element with the least priority .</returns>
public TElement Dequeue()
{
if (head == null)
{
throw new InvalidOperationException("Queue is empty");
}

var item = head;
head = item.Next;
return item.Element;
}

private class Item(TElement element, TPriority priority, Item? next)
{
public TElement Element => element;

public TPriority Priority => priority;

public Item? Next { get; set; } = next;
}
}
9 changes: 9 additions & 0 deletions PriorityQueue/PriorityQueue/PriorityQueue.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Что-то StyleCop не подключен, ни тут, ни в тестах. А GlobalSuppressions для него есть

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Он в Directory.Build.props в корне


</Project>