38 changed files with 13 additions and 4242 deletions
@ -1,19 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
/* |
|||
Copyright 2007-2013 The NGenerics Team |
|||
(https://github.com/ngenerics/ngenerics/wiki/Team)
|
|||
|
|||
This program is licensed under the GNU Lesser General Public License (LGPL). You should |
|||
have received a copy of the license along with the source code. If not, an online copy |
|||
of the license can be found at http://www.gnu.org/copyleft/lesser.html.
|
|||
*/ |
|||
|
|||
namespace NGenerics |
|||
{ |
|||
internal static class Constants |
|||
{ |
|||
public const string NotEnoughSpaceInTheTargetArray = "Not enough space in the target array."; |
|||
} |
|||
} |
|||
@ -1,80 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
/* |
|||
Copyright 2007-2013 The NGenerics Team |
|||
(https://github.com/ngenerics/ngenerics/wiki/Team)
|
|||
|
|||
This program is licensed under the GNU Lesser General Public License (LGPL). You should |
|||
have received a copy of the license along with the source code. If not, an online copy |
|||
of the license can be found at http://www.gnu.org/copyleft/lesser.html.
|
|||
*/ |
|||
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using NGenerics.Util; |
|||
|
|||
namespace NGenerics.Comparers |
|||
{ |
|||
/// <summary>
|
|||
/// A Comparer using a Comparison delegate for comparisons between items.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The type of the objects to compare.</typeparam>
|
|||
//[Serializable]
|
|||
public sealed class ComparisonComparer<T> : IComparer<T> |
|||
{ |
|||
#region Globals
|
|||
|
|||
private Comparison<T> _comparison; |
|||
|
|||
#endregion
|
|||
|
|||
#region Construction
|
|||
|
|||
|
|||
/// <param name="comparison">The comparison.</param>
|
|||
/// <exception cref="ArgumentNullException"><paramref name="comparison"/> is a null reference (<c>Nothing</c> in Visual Basic).</exception>
|
|||
public ComparisonComparer(Comparison<T> comparison) |
|||
{ |
|||
Guard.ArgumentNotNull(comparison, "comparison"); |
|||
|
|||
_comparison = comparison; |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region Public Members
|
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the comparison used in this comparer.
|
|||
/// </summary>
|
|||
/// <value>The comparison used in this comparer.</value>
|
|||
/// <exception cref="ArgumentNullException"><paramref name="value"/> is a null reference (<c>Nothing</c> in Visual Basic).</exception>
|
|||
public Comparison<T> Comparison |
|||
{ |
|||
get |
|||
{ |
|||
return _comparison; |
|||
} |
|||
set |
|||
{ |
|||
Guard.ArgumentNotNull(value, "value"); |
|||
|
|||
_comparison = value; |
|||
} |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region IComparer<T> Members
|
|||
|
|||
/// <inheritdoc />
|
|||
public int Compare(T x, T y) |
|||
{ |
|||
return _comparison(x, y); |
|||
} |
|||
|
|||
#endregion
|
|||
} |
|||
} |
|||
@ -1,93 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
/* |
|||
Copyright 2007-2013 The NGenerics Team |
|||
(https://github.com/ngenerics/ngenerics/wiki/Team)
|
|||
|
|||
This program is licensed under the GNU Lesser General Public License (LGPL). You should |
|||
have received a copy of the license along with the source code. If not, an online copy |
|||
of the license can be found at http://www.gnu.org/copyleft/lesser.html.
|
|||
*/ |
|||
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace NGenerics.Comparers |
|||
{ |
|||
/// <summary>
|
|||
/// A comparer for comparing keys for the KeyValuePair class.
|
|||
/// </summary>
|
|||
/// <typeparam name="TKey">The key type.</typeparam>
|
|||
/// <typeparam name="TValue">The value type.</typeparam>
|
|||
//[Serializable]
|
|||
public class KeyValuePairComparer<TKey, TValue> : IComparer<KeyValuePair<TKey, TValue>> |
|||
{ |
|||
#region Globals
|
|||
|
|||
private readonly IComparer<TKey> _comparer; |
|||
|
|||
#endregion
|
|||
|
|||
#region Construction
|
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="KeyValuePairComparer<TKey, TValue>"/> class.
|
|||
/// </summary>
|
|||
public KeyValuePairComparer() |
|||
{ |
|||
_comparer = Comparer<TKey>.Default; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="KeyValuePairComparer<TKey, TValue>"/> class.
|
|||
/// </summary>
|
|||
/// <param name="comparer">The comparer.</param>
|
|||
public KeyValuePairComparer(IComparer<TKey> comparer) |
|||
{ |
|||
if (comparer == null) |
|||
{ |
|||
throw new ArgumentNullException("comparer"); |
|||
} |
|||
|
|||
_comparer = comparer; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="KeyValuePairComparer<TKey, TValue>"/> class.
|
|||
/// </summary>
|
|||
/// <param name="comparison">The comparison.</param>
|
|||
public KeyValuePairComparer(Comparison<TKey> comparison) |
|||
{ |
|||
if (comparison == null) |
|||
{ |
|||
throw new ArgumentNullException("comparison"); |
|||
} |
|||
|
|||
_comparer = new ComparisonComparer<TKey>(comparison); |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region IComparer<KeyValuePairComparer<TKey,TValue>> Members
|
|||
|
|||
/// <inheritdoc />
|
|||
public int Compare(KeyValuePair<TKey, TValue> x, KeyValuePair<TKey, TValue> y) |
|||
{ |
|||
return _comparer.Compare(x.Key, y.Key); |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region IComparer<TKey> Members
|
|||
|
|||
/// <inheritdoc />
|
|||
public int Compare(TKey x, TKey y) |
|||
{ |
|||
return _comparer.Compare(x, y); |
|||
} |
|||
|
|||
#endregion
|
|||
} |
|||
} |
|||
@ -1,84 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
/* |
|||
Copyright 2007-2013 The NGenerics Team |
|||
(https://github.com/ngenerics/ngenerics/wiki/Team)
|
|||
|
|||
This program is licensed under the GNU Lesser General Public License (LGPL). You should |
|||
have received a copy of the license along with the source code. If not, an online copy |
|||
of the license can be found at http://www.gnu.org/copyleft/lesser.html.
|
|||
*/ |
|||
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using NGenerics.Util; |
|||
|
|||
namespace NGenerics.Comparers |
|||
{ |
|||
/// <summary>
|
|||
/// A comparer that wraps the IComparable interface to reproduce the opposite comparison result.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The type of the objects to compare.</typeparam>
|
|||
//[Serializable]
|
|||
public sealed class ReverseComparer<T> : IComparer<T> |
|||
{ |
|||
#region Globals
|
|||
|
|||
private IComparer<T> _comparerToUse; |
|||
|
|||
#endregion
|
|||
|
|||
#region Construction
|
|||
/// <inheritdoc />
|
|||
public ReverseComparer() |
|||
{ |
|||
_comparerToUse = Comparer<T>.Default; |
|||
} |
|||
|
|||
|
|||
/// <param name="comparer">The comparer to reverse.</param>
|
|||
/// <exception cref="ArgumentNullException"><paramref name="comparer"/> is a null reference (<c>Nothing</c> in Visual Basic).</exception>
|
|||
public ReverseComparer(IComparer<T> comparer) |
|||
{ |
|||
Guard.ArgumentNotNull(comparer, "comparer"); |
|||
_comparerToUse = comparer; |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region IComparer<T> Members
|
|||
|
|||
/// <inheritdoc />
|
|||
public int Compare(T x, T y) |
|||
{ |
|||
return (_comparerToUse.Compare(y, x)); |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region Public Members
|
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the comparer used in this instance.
|
|||
/// </summary>
|
|||
/// <value>The comparer.</value>
|
|||
/// <exception cref="ArgumentNullException"><paramref name="value"/> is a null reference (<c>Nothing</c> in Visual Basic).</exception>
|
|||
public IComparer<T> Comparer |
|||
{ |
|||
get |
|||
{ |
|||
return _comparerToUse; |
|||
} |
|||
set |
|||
{ |
|||
Guard.ArgumentNotNull(value, "value"); |
|||
|
|||
_comparerToUse = value; |
|||
} |
|||
} |
|||
|
|||
#endregion
|
|||
} |
|||
} |
|||
@ -1,405 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
/* |
|||
Copyright 2007-2013 The NGenerics Team |
|||
(https://github.com/ngenerics/ngenerics/wiki/Team)
|
|||
|
|||
This program is licensed under the GNU Lesser General Public License (LGPL). You should |
|||
have received a copy of the license along with the source code. If not, an online copy |
|||
of the license can be found at http://www.gnu.org/copyleft/lesser.html.
|
|||
*/ |
|||
|
|||
|
|||
using System; |
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
using NGenerics.Comparers; |
|||
using System.Diagnostics.CodeAnalysis; |
|||
using NGenerics.Util; |
|||
|
|||
namespace NGenerics.DataStructures.General |
|||
{ |
|||
/// <summary>
|
|||
/// An implementation of a Heap data structure.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The type of item stored in the <see cref="Heap{T}"/>.</typeparam>
|
|||
//[Serializable]
|
|||
[SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")] |
|||
[SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")] |
|||
public class Heap<T> : ICollection<T>, IHeap<T> |
|||
{ |
|||
#region Globals
|
|||
|
|||
private const string heapIsEmpty = "The heap is empty."; |
|||
private readonly List<T> _data; |
|||
private readonly IComparer<T> _comparerToUse; |
|||
private readonly HeapType _thisType; |
|||
|
|||
#endregion
|
|||
|
|||
#region Construction
|
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Heap<T>"/> class.
|
|||
/// </summary>
|
|||
/// <param name="type">The type of Heap to create.</param>
|
|||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="type"/> is not either <see cref="HeapType.Maximum"/> or <see cref="HeapType.Minimum"/> .</exception>
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\General\HeapExamples.cs" region="Constructor" lang="cs" title="The following example shows how to use the default constructor."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\General\HeapExamples.vb" region="Constructor" lang="vbnet" title="The following example shows how to use the default constructor."/>
|
|||
/// </example>
|
|||
public Heap(HeapType type) : this(type, Comparer<T>.Default) { } |
|||
|
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Heap<T>"/> class.
|
|||
/// </summary>
|
|||
/// <param name="type">The type of heap.</param>
|
|||
/// <param name="capacity">The capacity.</param>
|
|||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="type"/> is not either <see cref="HeapType.Maximum"/> or <see cref="HeapType.Minimum"/> .</exception>
|
|||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="capacity"/> is less than 0.</exception>
|
|||
/// .
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\General\HeapExamples.cs" region="ConstructorCapacity" lang="cs" title="The following example shows how to use the capacity constructor."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\General\HeapExamples.vb" region="ConstructorCapacity" lang="vbnet" title="The following example shows how to use the capacity constructor."/>
|
|||
/// </example>
|
|||
public Heap(HeapType type, int capacity) : this(type, capacity, Comparer<T>.Default) { } |
|||
|
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Heap<T>"/> class.
|
|||
/// </summary>
|
|||
/// <param name="type">The type of heap.</param>
|
|||
/// <param name="comparer">The comparer.</param>
|
|||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="type"/> is not either <see cref="HeapType.Maximum"/> or <see cref="HeapType.Minimum"/> .</exception>
|
|||
public Heap(HeapType type, Comparison<T> comparer) : this(type, new ComparisonComparer<T>(comparer)) { } |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Heap<T>"/> class.
|
|||
/// </summary>
|
|||
/// <param name="type">The type of heap.</param>
|
|||
/// <param name="capacity">The capacity of the heap to start with.</param>
|
|||
/// <param name="comparer">The comparer.</param>
|
|||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="type"/> is not either <see cref="HeapType.Maximum"/> or <see cref="HeapType.Minimum"/> .</exception>
|
|||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="capacity"/> is less than 0.</exception>
|
|||
public Heap(HeapType type, int capacity, Comparison<T> comparer) : this(type, capacity, new ComparisonComparer<T>(comparer)) { } |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Heap<T>"/> class.
|
|||
/// </summary>
|
|||
/// <param name="type">The type of Heap to create.</param>
|
|||
/// <param name="comparer">The comparer to use.</param>
|
|||
/// <exception cref="ArgumentNullException"><paramref name="comparer"/> is a null reference (<c>Nothing</c> in Visual Basic).</exception>
|
|||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="type"/> is not either <see cref="HeapType.Maximum"/> or <see cref="HeapType.Minimum"/> .</exception>
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\General\HeapExamples.cs" region="ConstructorComparer" lang="cs" title="The following example shows how to use the comparer constructor."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\General\HeapExamples.vb" region="ConstructorComparer" lang="vbnet" title="The following example shows how to use the comparer constructor."/>
|
|||
/// </example>
|
|||
public Heap(HeapType type, IComparer<T> comparer) |
|||
{ |
|||
Guard.ArgumentNotNull(comparer, "comparer"); |
|||
|
|||
if ((type != HeapType.Minimum) && (type != HeapType.Maximum)) |
|||
{ |
|||
throw new ArgumentOutOfRangeException("type"); |
|||
} |
|||
|
|||
_thisType = type; |
|||
|
|||
_data = new List<T> { default(T) }; |
|||
|
|||
_comparerToUse = type == HeapType.Minimum ? comparer : new ReverseComparer<T>(comparer); |
|||
} |
|||
|
|||
|
|||
/// <param name="type">The type of heap.</param>
|
|||
/// <param name="capacity">The initial capacity of the Heap.</param>
|
|||
/// <param name="comparer">The comparer to use.</param>
|
|||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="capacity"/> is less than 0.</exception>.
|
|||
/// <exception cref="ArgumentNullException"><paramref name="comparer"/> is a null reference (<c>Nothing</c> in Visual Basic).</exception>
|
|||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="type"/> is not either <see cref="HeapType.Maximum"/> or <see cref="HeapType.Minimum"/> .</exception>
|
|||
public Heap(HeapType type, int capacity, IComparer<T> comparer) |
|||
{ |
|||
Guard.ArgumentNotNull(comparer, "comparer"); |
|||
|
|||
if ((type != HeapType.Minimum) && (type != HeapType.Maximum)) |
|||
{ |
|||
throw new ArgumentOutOfRangeException("type"); |
|||
} |
|||
_thisType = type; |
|||
|
|||
_data = new List<T>(capacity) { default(T) }; |
|||
|
|||
_comparerToUse = type == HeapType.Minimum ? comparer : new ReverseComparer<T>(comparer); |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region Public Members
|
|||
|
|||
|
|||
/// <inheritdoc />
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\General\HeapExamples.cs" region="Root" lang="cs" title="The following example shows how to use the Root property."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\General\HeapExamples.vb" region="Root" lang="vbnet" title="The following example shows how to use the Root property."/>
|
|||
/// </example>
|
|||
public T Root |
|||
{ |
|||
get |
|||
{ |
|||
#region Validation
|
|||
|
|||
if (Count == 0) |
|||
{ |
|||
throw new InvalidOperationException(heapIsEmpty); |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
return _data[1]; |
|||
} |
|||
} |
|||
|
|||
|
|||
/// <inheritdoc />
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\General\HeapExamples.cs" region="RemoveRoot" lang="cs" title="The following example shows how to use the RemoveRoot method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\General\HeapExamples.vb" region="RemoveRoot" lang="vbnet" title="The following example shows how to use the RemoveRoot method."/>
|
|||
/// </example>
|
|||
public T RemoveRoot() |
|||
{ |
|||
#region Validation
|
|||
|
|||
if (Count == 0) |
|||
{ |
|||
throw new InvalidOperationException(heapIsEmpty); |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
// The minimum item to return.
|
|||
var minimum = _data[1]; |
|||
|
|||
RemoveRootItem(minimum); |
|||
return minimum; |
|||
} |
|||
|
|||
|
|||
/// <summary>
|
|||
/// Removes the root item.
|
|||
/// </summary>
|
|||
/// <param name="item">The item.</param>
|
|||
/// <remarks>
|
|||
/// <b>Notes to Inheritors: </b>
|
|||
/// Derived classes can override this method to change the behavior of the <see cref="RemoveRoot"/> method.
|
|||
/// </remarks>
|
|||
protected virtual void RemoveRootItem(T item) |
|||
{ |
|||
// The last item in the heap
|
|||
var last = _data[Count]; |
|||
_data.RemoveAt(Count); |
|||
|
|||
// If there's still items left in this heap, re-heapify it.
|
|||
if (Count > 0) |
|||
{ |
|||
// Re-heapify the binary tree to conform to the heap property
|
|||
var counter = 1; |
|||
|
|||
while ((counter * 2) < (_data.Count)) |
|||
{ |
|||
var child = counter * 2; |
|||
|
|||
if (((child + 1) < (_data.Count)) && |
|||
(_comparerToUse.Compare(_data[child + 1], _data[child]) < 0)) |
|||
{ |
|||
child++; |
|||
} |
|||
|
|||
if (_comparerToUse.Compare(last, _data[child]) <= 0) |
|||
{ |
|||
break; |
|||
} |
|||
|
|||
_data[counter] = _data[child]; |
|||
counter = child; |
|||
} |
|||
|
|||
_data[counter] = last; |
|||
} |
|||
} |
|||
|
|||
|
|||
/// <summary>
|
|||
/// Gets the type of heap represented by this instance.
|
|||
/// </summary>
|
|||
/// <value>The type of heap.</value>
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\General\HeapExamples.cs" region="Type" lang="cs" title="The following example shows how to use the Type property."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\General\HeapExamples.vb" region="Type" lang="vbnet" title="The following example shows how to use the Type property."/>
|
|||
/// </example>
|
|||
[SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods")] |
|||
public HeapType Type => _thisType; |
|||
|
|||
#endregion
|
|||
|
|||
#region ICollection<T> Members
|
|||
|
|||
|
|||
|
|||
/// <inheritdoc />
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\General\HeapExamples.cs" region="IsEmpty" lang="cs" title="The following example shows how to use the IsEmpty property."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\General\HeapExamples.vb" region="IsEmpty" lang="vbnet" title="The following example shows how to use the IsEmpty property."/>
|
|||
/// </example>
|
|||
public bool IsEmpty => Count == 0; |
|||
|
|||
|
|||
/// <inheritdoc />
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\General\HeapExamples.cs" region="Contains" lang="cs" title="The following example shows how to use the Contains method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\General\HeapExamples.vb" region="Contains" lang="vbnet" title="The following example shows how to use the Contains method."/>
|
|||
/// </example>
|
|||
public bool Contains(T item) |
|||
{ |
|||
return _data.Contains(item); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\General\HeapExamples.cs" region="CopyTo" lang="cs" title="The following example shows how to use the CopyTo method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\General\HeapExamples.vb" region="CopyTo" lang="vbnet" title="The following example shows how to use the CopyTo method."/>
|
|||
/// </example>
|
|||
public void CopyTo(T[] array, int arrayIndex) |
|||
{ |
|||
#region Validation
|
|||
|
|||
Guard.ArgumentNotNull(array, "array"); |
|||
|
|||
if ((array.Length - arrayIndex) < Count) |
|||
{ |
|||
throw new ArgumentException(Constants.NotEnoughSpaceInTheTargetArray, "array"); |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
for (var i = 1; i < _data.Count; i++) |
|||
{ |
|||
array[arrayIndex++] = _data[i]; |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\General\HeapExamples.cs" region="Count" lang="cs" title="The following example shows how to use the Count property."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\General\HeapExamples.vb" region="Count" lang="vbnet" title="The following example shows how to use the Count property."/>
|
|||
/// </example>
|
|||
public int Count => _data.Count - 1; |
|||
|
|||
/// <inheritdoc />
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\General\HeapExamples.cs" region="Add" lang="cs" title="The following example shows how to use the Add method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\General\HeapExamples.vb" region="Add" lang="vbnet" title="The following example shows how to use the Add method."/>
|
|||
/// </example>
|
|||
public void Add(T item) |
|||
{ |
|||
AddItem(item); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adds the item.
|
|||
/// </summary>
|
|||
/// <param name="item">The item to add.</param>
|
|||
/// <remarks>
|
|||
/// <b>Notes to Inheritors: </b>
|
|||
/// Derived classes can override this method to change the behavior of the <see cref="Add"/> method.
|
|||
/// </remarks>
|
|||
protected virtual void AddItem(T item) |
|||
{ |
|||
// Add a dummy to the end of the list (it will be replaced)
|
|||
_data.Add(default(T)); |
|||
|
|||
var counter = _data.Count - 1; |
|||
|
|||
while ((counter > 1) && (_comparerToUse.Compare(_data[counter / 2], item) > 0)) |
|||
{ |
|||
_data[counter] = _data[counter / 2]; |
|||
counter = counter / 2; |
|||
} |
|||
|
|||
_data[counter] = item; |
|||
} |
|||
|
|||
|
|||
|
|||
/// <inheritdoc />
|
|||
/// <exception cref="NotSupportedException">Always.</exception>
|
|||
[SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")] |
|||
bool ICollection<T>.Remove(T item) |
|||
{ |
|||
throw new NotSupportedException(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns an enumerator that iterates through the collection.
|
|||
/// </summary>
|
|||
/// <returns>
|
|||
/// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
|
|||
/// </returns>
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\General\HeapExamples.cs" region="GetEnumerator" lang="cs" title="The following example shows how to use the GetEnumerator method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\General\HeapExamples.vb" region="GetEnumerator" lang="vbnet" title="The following example shows how to use the GetEnumerator method."/>
|
|||
/// </example>
|
|||
public IEnumerator<T> GetEnumerator() |
|||
{ |
|||
for (var i = 1; i < _data.Count; i++) |
|||
{ |
|||
yield return _data[i]; |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\General\HeapExamples.cs" region="Clear" lang="cs" title="The following example shows how to use the Clear method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\General\HeapExamples.vb" region="Clear" lang="vbnet" title="The following example shows how to use the Clear method."/>
|
|||
/// </example>
|
|||
public void Clear() |
|||
{ |
|||
ClearItems(); |
|||
} |
|||
/// <summary>
|
|||
/// Clears all the objects in this instance.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// <b>Notes to Inheritors: </b>
|
|||
/// Derived classes can override this method to change the behavior of the <see cref="Clear"/> method.
|
|||
/// </remarks>
|
|||
protected virtual void ClearItems() |
|||
{ |
|||
_data.RemoveRange(1, _data.Count - 1); // Clears all objects in this instance except the first dummy one.
|
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region ICollection<T> Members
|
|||
|
|||
/// <inheritdoc />
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\General\HeapExamples.cs" region="IsReadOnly" lang="cs" title="The following example shows how to use the IsReadOnly property."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\General\HeapExamples.vb" region="IsReadOnly" lang="vbnet" title="The following example shows how to use the IsReadOnly property."/>
|
|||
/// </example>
|
|||
public bool IsReadOnly => false; |
|||
|
|||
#endregion
|
|||
|
|||
#region IEnumerable Members
|
|||
|
|||
/// <inheritdoc />
|
|||
IEnumerator IEnumerable.GetEnumerator() |
|||
{ |
|||
return GetEnumerator(); |
|||
} |
|||
|
|||
#endregion
|
|||
} |
|||
} |
|||
@ -1,32 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
/* |
|||
Copyright 2007-2013 The NGenerics Team |
|||
(https://github.com/ngenerics/ngenerics/wiki/Team)
|
|||
|
|||
This program is licensed under the GNU Lesser General Public License (LGPL). You should |
|||
have received a copy of the license along with the source code. If not, an online copy |
|||
of the license can be found at http://www.gnu.org/copyleft/lesser.html.
|
|||
*/ |
|||
|
|||
|
|||
|
|||
namespace NGenerics.DataStructures.General |
|||
{ |
|||
/// <summary>
|
|||
/// The type of <see cref="Heap{T}"/> to implemented.
|
|||
/// </summary>
|
|||
public enum HeapType |
|||
{ |
|||
/// <summary>
|
|||
/// Makes the heap a Minimum-Heap - the smallest item is kept in the root of the <see cref="Heap{T}"/>.
|
|||
/// </summary>
|
|||
Minimum, |
|||
|
|||
/// <summary>
|
|||
/// Makes the heap a Maximum-Heap - the largest item is kept in the root of the <see cref="Heap{T}"/>.
|
|||
/// </summary>
|
|||
Maximum |
|||
} |
|||
} |
|||
@ -1,44 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
/* |
|||
Copyright 2007-2013 The NGenerics Team |
|||
(https://github.com/ngenerics/ngenerics/wiki/Team)
|
|||
|
|||
This program is licensed under the GNU Lesser General Public License (LGPL). You should |
|||
have received a copy of the license along with the source code. If not, an online copy |
|||
of the license can be found at http://www.gnu.org/copyleft/lesser.html.
|
|||
*/ |
|||
|
|||
|
|||
using System; |
|||
|
|||
namespace NGenerics.DataStructures.General |
|||
{ |
|||
/// <summary>
|
|||
/// An interface for the <see cref="Heap{T}"/> data structure.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The type of elements in the heap.</typeparam>
|
|||
public interface IHeap<T> |
|||
{ |
|||
/// <summary>
|
|||
/// Adds the specified item.
|
|||
/// </summary>
|
|||
/// <param name="item">The item.</param>
|
|||
void Add(T item); |
|||
|
|||
/// <summary>
|
|||
/// Removes the root and returns it.
|
|||
/// </summary>
|
|||
/// <returns>The root of the <see cref="Heap{T}"/>.</returns>
|
|||
/// <exception cref="InvalidOperationException">The <see cref="Graph{T}"/> is empty.</exception>
|
|||
T RemoveRoot(); |
|||
|
|||
/// <summary>
|
|||
/// Gets the root.
|
|||
/// </summary>
|
|||
/// <value>The root.</value>
|
|||
/// <exception cref="InvalidOperationException">The <see cref="Heap{T}"/> is empty.</exception>
|
|||
T Root { get; } |
|||
} |
|||
} |
|||
@ -1,46 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
/* |
|||
Copyright 2007-2013 The NGenerics Team |
|||
(https://github.com/ngenerics/ngenerics/wiki/Team)
|
|||
|
|||
This program is licensed under the GNU Lesser General Public License (LGPL). You should |
|||
have received a copy of the license along with the source code. If not, an online copy |
|||
of the license can be found at http://www.gnu.org/copyleft/lesser.html.
|
|||
*/ |
|||
|
|||
|
|||
using System; |
|||
using System.Diagnostics.CodeAnalysis; |
|||
|
|||
namespace NGenerics.DataStructures.Queues |
|||
{ |
|||
/// <summary>
|
|||
/// A queue interface.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The type of the elements in the queue.</typeparam>
|
|||
[SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")] |
|||
public interface IQueue<T> |
|||
{ |
|||
/// <summary>
|
|||
/// Enqueues the item at the back of the queue.
|
|||
/// </summary>
|
|||
/// <param name="item">The item.</param>
|
|||
void Enqueue(T item); |
|||
|
|||
/// <summary>
|
|||
/// Dequeues the item at the front of the queue.
|
|||
/// </summary>
|
|||
/// <returns>The item at the front of the queue.</returns>
|
|||
/// <exception cref="InvalidOperationException">The <see cref="Deque{T}"/> is empty.</exception>
|
|||
T Dequeue(); |
|||
|
|||
/// <summary>
|
|||
/// Peeks at the item in the front of the queue, without removing it.
|
|||
/// </summary>
|
|||
/// <returns>The item at the front of the queue.</returns>
|
|||
/// <exception cref="InvalidOperationException">The <see cref="Deque{T}"/> is empty.</exception>
|
|||
T Peek(); |
|||
} |
|||
} |
|||
@ -1,556 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
/* |
|||
Copyright 2007-2013 The NGenerics Team |
|||
(https://github.com/ngenerics/ngenerics/wiki/Team)
|
|||
|
|||
This program is licensed under the GNU Lesser General Public License (LGPL). You should |
|||
have received a copy of the license along with the source code. If not, an online copy |
|||
of the license can be found at http://www.gnu.org/copyleft/lesser.html.
|
|||
|
|||
Community contributions : |
|||
- TKey Peek(out TPriority) contributed by Karl Shulze (http://www.karlschulze.com/).</remarks>
|
|||
*/ |
|||
|
|||
|
|||
using System; |
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
using System.Diagnostics.CodeAnalysis; |
|||
using NGenerics.Comparers; |
|||
using NGenerics.DataStructures.Trees; |
|||
using NGenerics.Util; |
|||
|
|||
namespace NGenerics.DataStructures.Queues |
|||
{ |
|||
/// <summary>
|
|||
/// An implementation of a Priority Queue (can be <see cref="PriorityQueueType.Minimum"/> or <see cref="PriorityQueueType.Maximum"/>).
|
|||
/// </summary>
|
|||
/// <typeparam name="TPriority">The type of the priority in the <see cref="PriorityQueue{TPriority, TValue}"/>.</typeparam>
|
|||
/// <typeparam name="TValue">The type of the elements in the <see cref="PriorityQueue{TPriority, TValue}"/>.</typeparam>
|
|||
[SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")] |
|||
[SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")] |
|||
//[Serializable]
|
|||
public class PriorityQueue<TValue, TPriority> : ICollection<TValue>, IQueue<TValue> |
|||
{ |
|||
#region Globals
|
|||
|
|||
private readonly RedBlackTreeList<TPriority, TValue> _tree; |
|||
private TPriority _defaultPriority; |
|||
private readonly PriorityQueueType _queueType; |
|||
|
|||
#endregion
|
|||
|
|||
#region Construction
|
|||
|
|||
/// <param name="queueType">Type of the queue.</param>
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Queues\PriorityQueueExamples.cs" region="Constructor" lang="cs" title="The following example shows how to use the default constructor."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Queues\PriorityQueueExamples.vb" region="Constructor" lang="vbnet" title="The following example shows how to use the default constructor."/>
|
|||
/// </example>
|
|||
public PriorityQueue(PriorityQueueType queueType) : |
|||
this(queueType, Comparer<TPriority>.Default) |
|||
{ |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public PriorityQueue(PriorityQueueType queueType, IComparer<TPriority> comparer) |
|||
{ |
|||
if ((queueType != PriorityQueueType.Minimum) && (queueType != PriorityQueueType.Maximum)) |
|||
{ |
|||
throw new ArgumentOutOfRangeException("queueType"); |
|||
} |
|||
_queueType = queueType; |
|||
_tree = new RedBlackTreeList<TPriority, TValue>(comparer); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="PriorityQueue<TValue, TPriority>"/> class.
|
|||
/// </summary>
|
|||
/// <param name="queueType">Type of the queue.</param>
|
|||
/// <param name="comparison">The comparison.</param>
|
|||
/// <inheritdoc/>
|
|||
public PriorityQueue(PriorityQueueType queueType, Comparison<TPriority> comparison) : |
|||
this(queueType, new ComparisonComparer<TPriority>(comparison)) |
|||
{ |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region IQueue<T> Members
|
|||
|
|||
/// <inheritdoc />
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Queues\PriorityQueueExamples.cs" region="Enqueue" lang="cs" title="The following example shows how to use the Enqueue method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Queues\PriorityQueueExamples.vb" region="Enqueue" lang="vbnet" title="The following example shows how to use the Enqueue method."/>
|
|||
/// </example>
|
|||
public void Enqueue(TValue item) |
|||
{ |
|||
Add(item); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Enqueues the specified item.
|
|||
/// </summary>
|
|||
/// <param name="item">The item.</param>
|
|||
/// <param name="priority">The priority.</param>
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Queues\PriorityQueueExamples.cs" region="EnqueuePriority" lang="cs" title="The following example shows how to use the Enqueue method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Queues\PriorityQueueExamples.vb" region="EnqueuePriority" lang="vbnet" title="The following example shows how to use the Enqueue method."/>
|
|||
/// </example>
|
|||
public void Enqueue(TValue item, TPriority priority) |
|||
{ |
|||
Add(item, priority); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Dequeues the item at the front of the queue.
|
|||
/// </summary>
|
|||
/// <returns>The item at the front of the queue.</returns>
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Queues\PriorityQueueExamples.cs" region="Dequeue" lang="cs" title="The following example shows how to use the Dequeue method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Queues\PriorityQueueExamples.vb" region="Dequeue" lang="vbnet" title="The following example shows how to use the Dequeue method."/>
|
|||
/// </example>
|
|||
public TValue Dequeue() |
|||
{ |
|||
TPriority priority; |
|||
return Dequeue(out priority); |
|||
} |
|||
|
|||
|
|||
/// <summary>
|
|||
/// Peeks at the item in the front of the queue, without removing it.
|
|||
/// </summary>
|
|||
/// <returns>The item at the front of the queue.</returns>
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Queues\PriorityQueueExamples.cs" region="Peek" lang="cs" title="The following example shows how to use the Peek method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Queues\PriorityQueueExamples.vb" region="Peek" lang="vbnet" title="The following example shows how to use the Peek method."/>
|
|||
/// </example>
|
|||
public TValue Peek() |
|||
{ |
|||
var association = GetNextItem(); |
|||
|
|||
// Always dequeue in FIFO manner
|
|||
return association.Value.First.Value; |
|||
} |
|||
|
|||
|
|||
/// <summary>
|
|||
/// Peeks at the item in the front of the queue, without removing it.
|
|||
/// </summary>
|
|||
/// <param name="priority">The priority of the item.</param>
|
|||
/// <returns>The item at the front of the queue.</returns>
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Queues\PriorityQueueExamples.cs" region="PeekPriority" lang="cs" title="The following example shows how to use the Peek method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Queues\PriorityQueueExamples.vb" region="PeekPriority" lang="vbnet" title="The following example shows how to use the Peek method."/>
|
|||
/// </example>
|
|||
public TValue Peek(out TPriority priority) |
|||
{ |
|||
var association = GetNextItem(); |
|||
var item = association.Value.First.Value; |
|||
priority = association.Key; |
|||
return item; |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region ICollection<T> Members
|
|||
|
|||
/// <inheritdoc />
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Queues\PriorityQueueExamples.cs" region="IsReadOnly" lang="cs" title="The following example shows how to use the IsReadOnly property."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Queues\PriorityQueueExamples.vb" region="IsReadOnly" lang="vbnet" title="The following example shows how to use the IsReadOnly property."/>
|
|||
/// </example>
|
|||
public bool IsReadOnly => false; |
|||
|
|||
#endregion
|
|||
|
|||
#region IEnumerable Members
|
|||
|
|||
/// <inheritdoc />
|
|||
IEnumerator IEnumerable.GetEnumerator() |
|||
{ |
|||
return GetEnumerator(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns an enumerator that iterates through the collection.
|
|||
/// </summary>
|
|||
/// <returns>
|
|||
/// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
|
|||
/// </returns>
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Queues\PriorityQueueExamples.cs" region="GetEnumerator" lang="cs" title="The following example shows how to use the GetEnumerator method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Queues\PriorityQueueExamples.vb" region="GetEnumerator" lang="vbnet" title="The following example shows how to use the GetEnumerator method."/>
|
|||
/// </example>
|
|||
public IEnumerator<TValue> GetEnumerator() |
|||
{ |
|||
return _tree.GetValueEnumerator(); |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region Public Members
|
|||
|
|||
/// <inheritdoc />
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Queues\PriorityQueueExamples.cs" region="Count" lang="cs" title="The following example shows how to use the Count property."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Queues\PriorityQueueExamples.vb" region="Count" lang="vbnet" title="The following example shows how to use the Count property."/>
|
|||
/// </example>
|
|||
public int Count { get; private set; } |
|||
|
|||
/// <inheritdoc />
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Queues\PriorityQueueExamples.cs" region="Contains" lang="cs" title="The following example shows how to use the Contains method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Queues\PriorityQueueExamples.vb" region="Contains" lang="vbnet" title="The following example shows how to use the Contains method."/>
|
|||
/// </example>
|
|||
public bool Contains(TValue item) |
|||
{ |
|||
return _tree.ContainsValue(item); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Queues\PriorityQueueExamples.cs" region="CopyTo" lang="cs" title="The following example shows how to use the CopyTo method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Queues\PriorityQueueExamples.vb" region="CopyTo" lang="vbnet" title="The following example shows how to use the CopyTo method."/>
|
|||
/// </example>
|
|||
public void CopyTo(TValue[] array, int arrayIndex) |
|||
{ |
|||
#region Validation
|
|||
|
|||
Guard.ArgumentNotNull(array, "array"); |
|||
|
|||
if ((array.Length - arrayIndex) < Count) |
|||
{ |
|||
throw new ArgumentException(Constants.NotEnoughSpaceInTheTargetArray, "array"); |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
|
|||
foreach (var association in _tree) |
|||
{ |
|||
var items = association.Value; |
|||
|
|||
foreach (var item in items) |
|||
{ |
|||
array.SetValue(item, arrayIndex++); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Queues\PriorityQueueExamples.cs" region="Add" lang="cs" title="The following example shows how to use the Add method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Queues\PriorityQueueExamples.vb" region="Add" lang="vbnet" title="The following example shows how to use the Add method."/>
|
|||
/// </example>
|
|||
public void Add(TValue item) |
|||
{ |
|||
Add(item, _defaultPriority); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adds an item to the <see cref="ICollection{T}"/>.
|
|||
/// </summary>
|
|||
/// <param name="item">The object to add to the <see cref="ICollection{T}"/>.</param>
|
|||
/// <param name="priority">The priority of the item.</param>
|
|||
/// <exception cref="NotSupportedException">The <see cref="ICollection{T}"/> is read-only.</exception>
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Queues\PriorityQueueExamples.cs" region="AddPriority" lang="cs" title="The following example shows how to use the Add method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Queues\PriorityQueueExamples.vb" region="AddPriority" lang="vbnet" title="The following example shows how to use the Add method."/>
|
|||
/// </example>
|
|||
public void Add(TValue item, TPriority priority) |
|||
{ |
|||
AddItem(item, priority); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public bool Remove(TValue item) |
|||
{ |
|||
TPriority priority; |
|||
return Remove(item, out priority); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns an enumerator that iterates through the keys in the collection.
|
|||
/// </summary>
|
|||
/// <returns>A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the keys in the collection.</returns>
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Queues\PriorityQueueExamples.cs" region="GetKeyEnumerator" lang="cs" title="The following example shows how to use the GetKeyEnumerator method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Queues\PriorityQueueExamples.vb" region="GetKeyEnumerator" lang="vbnet" title="The following example shows how to use the GetKeyEnumerator method."/>
|
|||
/// </example>
|
|||
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")] |
|||
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")] |
|||
public IEnumerator<KeyValuePair<TPriority, TValue>> GetKeyEnumerator() |
|||
{ |
|||
return _tree.GetKeyEnumerator(); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Queues\PriorityQueueExamples.cs" region="Clear" lang="cs" title="The following example shows how to use the Clear method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Queues\PriorityQueueExamples.vb" region="Clear" lang="vbnet" title="The following example shows how to use the Clear method."/>
|
|||
/// </example>
|
|||
public void Clear() |
|||
{ |
|||
ClearItems(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Dequeues the item from the head of the queue.
|
|||
/// </summary>
|
|||
/// <param name="priority">The priority of the item to dequeue.</param>
|
|||
/// <returns>The item at the head of the queue.</returns>
|
|||
/// <exception cref="InvalidOperationException">The <see cref="PriorityQueue{TValue, TPriority}"/> is empty.</exception>
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Queues\PriorityQueueExamples.cs" region="DequeueWithPriority" lang="cs" title="The following example shows how to use the Dequeue method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Queues\PriorityQueueExamples.vb" region="DequeueWithPriority" lang="vbnet" title="The following example shows how to use the Dequeue method."/>
|
|||
/// </example>
|
|||
[SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "0#")] |
|||
public TValue Dequeue(out TPriority priority) |
|||
{ |
|||
return DequeueItem(out priority); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Dequeues the item at the front of the queue.
|
|||
/// </summary>
|
|||
/// <returns>The item at the front of the queue.</returns>
|
|||
/// <remarks>
|
|||
/// <b>Notes to Inheritors: </b>
|
|||
/// Derived classes can override this method to change the behavior of the <see cref="Dequeue()"/> or <see cref="Dequeue(out TPriority)"/> methods.
|
|||
/// </remarks>
|
|||
[SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "0#")] |
|||
protected virtual TValue DequeueItem(out TPriority priority) |
|||
{ |
|||
var association = GetNextItem(); |
|||
|
|||
var item = association.Value.First.Value; |
|||
association.Value.RemoveFirst(); |
|||
|
|||
var key = association.Key; |
|||
|
|||
if (association.Value.Count == 0) |
|||
{ |
|||
_tree.Remove(association.Key); |
|||
} |
|||
|
|||
Count--; |
|||
|
|||
priority = key; |
|||
return item; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the default priority.
|
|||
/// </summary>
|
|||
/// <value>The default priority.</value>
|
|||
public TPriority DefaultPriority |
|||
{ |
|||
get |
|||
{ |
|||
return _defaultPriority; |
|||
} |
|||
set |
|||
{ |
|||
_defaultPriority = value; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Removes the first occurrence of the specified item from the property queue.
|
|||
/// </summary>
|
|||
/// <param name="item">The item to remove.</param>
|
|||
/// <param name="priority">The priority associated with the item.</param>
|
|||
/// <returns><c>true</c> if the item exists in the <see cref="PriorityQueue{TValue, TPriority}"/> and has been removed; otherwise <c>false</c>.</returns>
|
|||
[SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "1#")] |
|||
public bool Remove(TValue item, out TPriority priority) |
|||
{ |
|||
return RemoveItem(item, out priority); |
|||
} |
|||
/// <summary>
|
|||
/// Removes the item.
|
|||
/// </summary>
|
|||
/// <param name="item">The item to remove</param>
|
|||
/// <param name="priority">The priority of the item that was removed.</param>
|
|||
/// <returns>An indication of whether the item was found, and removed.</returns>
|
|||
/// <remarks>
|
|||
/// <b>Notes to Inheritors: </b>
|
|||
/// Derived classes can override this method to change the behavior of the <see cref="Remove(TValue,out TPriority)"/> method.
|
|||
/// </remarks>
|
|||
[SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters", MessageId = "1#")] |
|||
protected virtual bool RemoveItem(TValue item, out TPriority priority) |
|||
{ |
|||
var removed = _tree.Remove(item, out priority); |
|||
|
|||
if (removed) |
|||
{ |
|||
Count--; |
|||
} |
|||
|
|||
return removed; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Removes the items with the specified priority.
|
|||
/// </summary>
|
|||
/// <param name="priority">The priority.</param>
|
|||
/// <returns><c>true</c> if the priority exists in the <see cref="PriorityQueue{TValue, TPriority}"/> and has been removed; otherwise <c>false</c>.</returns>
|
|||
public bool RemovePriorityGroup(TPriority priority) |
|||
{ |
|||
return RemoveItems(priority); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Removes the items from the collection with the specified priority.
|
|||
/// </summary>
|
|||
/// <param name="priority">The priority to search for.</param>
|
|||
/// <returns>An indication of whether items were found having the specified priority.</returns>
|
|||
protected virtual bool RemoveItems(TPriority priority) |
|||
{ |
|||
LinkedList<TValue> items; |
|||
|
|||
if (_tree.TryGetValue(priority, out items)) |
|||
{ |
|||
_tree.Remove(priority); |
|||
Count -= items.Count; |
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Removes the items with the specified priority.
|
|||
/// </summary>
|
|||
/// <param name="priority">The priority.</param>
|
|||
/// <returns>The items with the specified priority.</returns>
|
|||
public IList<TValue> GetPriorityGroup(TPriority priority) |
|||
{ |
|||
LinkedList<TValue> items; |
|||
|
|||
return _tree.TryGetValue(priority, out items) ? new List<TValue>(items) : new List<TValue>(); |
|||
} |
|||
|
|||
|
|||
/// <summary>
|
|||
/// Adds the specified items to the priority queue with the specified priority.
|
|||
/// </summary>
|
|||
/// <param name="items">The items.</param>
|
|||
/// <param name="priority">The priority.</param>
|
|||
/// <exception cref="ArgumentNullException"><paramref name="items"/> is a null reference (<c>Nothing</c> in Visual Basic).</exception>
|
|||
public void AddPriorityGroup(IList<TValue> items, TPriority priority) |
|||
{ |
|||
#region Validation
|
|||
|
|||
Guard.ArgumentNotNull(items, "items"); |
|||
|
|||
#endregion
|
|||
|
|||
AddPriorityGroupItem(items, priority); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adds the specified items to the priority queue with the specified priority.
|
|||
/// </summary>
|
|||
/// <param name="items">The items.</param>
|
|||
/// <param name="priority">The priority.</param>
|
|||
/// <remarks>
|
|||
/// <b>Notes to Inheritors: </b>
|
|||
/// Derived classes can override this method to change the behavior of the <see cref="AddPriorityGroup"/> method.
|
|||
/// </remarks>
|
|||
protected virtual void AddPriorityGroupItem(IList<TValue> items, TPriority priority) |
|||
{ |
|||
LinkedList<TValue> currentValues; |
|||
|
|||
if (_tree.TryGetValue(priority, out currentValues)) |
|||
{ |
|||
for (var i = 0; i < items.Count; i++) |
|||
{ |
|||
currentValues.AddLast(items[i]); |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
currentValues = new LinkedList<TValue>(items); |
|||
_tree.Add(priority, currentValues); |
|||
} |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region Protected Members
|
|||
|
|||
/// <summary>
|
|||
/// Adds the item to the queue.
|
|||
/// </summary>
|
|||
/// <param name="item">The item to add.</param>
|
|||
/// <param name="priority">The priority of the item.</param>
|
|||
/// <remarks>
|
|||
/// <b>Notes to Inheritors: </b>
|
|||
/// Derived classes can override this method to change the behavior of the <see cref="Add(TValue,TPriority)"/> method.
|
|||
/// </remarks>
|
|||
protected virtual void AddItem(TValue item, TPriority priority) |
|||
{ |
|||
LinkedList<TValue> list; |
|||
|
|||
if (_tree.TryGetValue(priority, out list)) |
|||
{ |
|||
list.AddLast(item); |
|||
} |
|||
else |
|||
{ |
|||
list = new LinkedList<TValue>(); |
|||
list.AddLast(item); |
|||
_tree.Add(priority, list); |
|||
} |
|||
|
|||
Count++; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Clears all the objects in this instance.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// <b>Notes to Inheritors: </b>
|
|||
/// Derived classes can override this method to change the behavior of the <see cref="Clear"/> method.
|
|||
/// </remarks>
|
|||
protected virtual void ClearItems() |
|||
{ |
|||
_tree.Clear(); |
|||
Count = 0; |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region Private Members
|
|||
|
|||
/// <summary>
|
|||
/// Checks if the list is not empty, and if it is, throw an exception.
|
|||
/// </summary>
|
|||
private void CheckTreeNotEmpty() |
|||
{ |
|||
if (_tree.Count == 0) |
|||
{ |
|||
throw new InvalidOperationException("The Priority Queue is empty."); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the next item.
|
|||
/// </summary>
|
|||
private KeyValuePair<TPriority, LinkedList<TValue>> GetNextItem() |
|||
{ |
|||
#region Validation
|
|||
|
|||
CheckTreeNotEmpty(); |
|||
|
|||
#endregion
|
|||
|
|||
return _queueType == PriorityQueueType.Maximum ? _tree.Maximum : _tree.Minimum; |
|||
} |
|||
|
|||
#endregion
|
|||
} |
|||
} |
|||
@ -1,30 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
/* |
|||
Copyright 2007-2013 The NGenerics Team |
|||
(https://github.com/ngenerics/ngenerics/wiki/Team)
|
|||
|
|||
This program is licensed under the GNU Lesser General Public License (LGPL). You should |
|||
have received a copy of the license along with the source code. If not, an online copy |
|||
of the license can be found at http://www.gnu.org/copyleft/lesser.html.
|
|||
*/ |
|||
|
|||
namespace NGenerics.DataStructures.Queues |
|||
{ |
|||
/// <summary>
|
|||
/// Specifies the Priority Queue type (min or max).
|
|||
/// </summary>
|
|||
public enum PriorityQueueType |
|||
{ |
|||
/// <summary>
|
|||
/// Specify a Minimum <see cref="PriorityQueue{TValue, TPriority}"/>.
|
|||
/// </summary>
|
|||
Minimum = 0, |
|||
|
|||
/// <summary>
|
|||
/// Specify a Maximum <see cref="PriorityQueue{TValue, TPriority}"/>.
|
|||
/// </summary>
|
|||
Maximum = 1 |
|||
} |
|||
} |
|||
@ -1,529 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
/* |
|||
Copyright 2007-2013 The NGenerics Team |
|||
(https://github.com/ngenerics/ngenerics/wiki/Team)
|
|||
|
|||
This program is licensed under the GNU Lesser General Public License (LGPL). You should |
|||
have received a copy of the license along with the source code. If not, an online copy |
|||
of the license can be found at http://www.gnu.org/copyleft/lesser.html.
|
|||
*/ |
|||
|
|||
using System; |
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
using System.Diagnostics; |
|||
using System.Diagnostics.CodeAnalysis; |
|||
using NGenerics.Comparers; |
|||
using NGenerics.Patterns.Visitor; |
|||
using NGenerics.Util; |
|||
|
|||
namespace NGenerics.DataStructures.Trees |
|||
{ |
|||
/// <summary>
|
|||
/// A base class for Binary Search Trees that store a single value in each node.
|
|||
/// </summary>
|
|||
/// <typeparam name="T"></typeparam>
|
|||
//[Serializable]
|
|||
public abstract class BinarySearchTreeBase<T> : ISearchTree<T> |
|||
{ |
|||
#region Globals
|
|||
|
|||
internal const string alreadyContainedInTheTree = "The item is already contained in the tree."; |
|||
private BinaryTree<T> _tree; |
|||
private readonly IComparer<T> _comparer; |
|||
|
|||
#endregion
|
|||
|
|||
#region Delegates
|
|||
|
|||
/// <summary>
|
|||
/// A custom comparison between some search value and the type of item that is kept in the tree.
|
|||
/// </summary>
|
|||
/// <typeparam name="TSearch">The type of the search.</typeparam>
|
|||
protected delegate int CustomComparison<TSearch>(TSearch value, T item); |
|||
|
|||
#endregion
|
|||
|
|||
#region Construction
|
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="BinarySearchTreeBase{T}"/> class.
|
|||
/// </summary>
|
|||
protected BinarySearchTreeBase() |
|||
{ |
|||
_comparer = Comparer<T>.Default; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="BinarySearchTreeBase{T}"/> class.
|
|||
/// </summary>
|
|||
/// <param name="comparer">The comparer to use when comparing items.</param>
|
|||
/// <exception cref="ArgumentNullException"><paramref name="comparer"/> is a null reference (<c>Nothing</c> in Visual Basic).</exception>
|
|||
protected BinarySearchTreeBase(IComparer<T> comparer) |
|||
{ |
|||
Guard.ArgumentNotNull(comparer, "comparer"); |
|||
_comparer = comparer; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="BinarySearchTreeBase<TKey, TValue>"/> class.
|
|||
/// </summary>
|
|||
/// <param name="comparison">The comparison.</param>
|
|||
protected BinarySearchTreeBase(Comparison<T> comparison) |
|||
{ |
|||
Guard.ArgumentNotNull(comparison, "comparison"); |
|||
_comparer = new ComparisonComparer<T>(comparison); |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region Public Members
|
|||
|
|||
/// <summary>
|
|||
/// Gets the comparer.
|
|||
/// </summary>
|
|||
/// <value>The comparer.</value>
|
|||
public IComparer<T> Comparer => _comparer; |
|||
|
|||
#endregion
|
|||
|
|||
#region Protected Members
|
|||
|
|||
/// <summary>
|
|||
/// Finds the node containing the specified data key.
|
|||
/// </summary>
|
|||
/// <param name="item">The item.</param>
|
|||
/// <returns>
|
|||
/// The node with the specified key if found. If the key is not in the tree, this method returns null.
|
|||
/// </returns>
|
|||
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")] |
|||
protected virtual BinaryTree<T> FindNode(T item) |
|||
{ |
|||
if (_tree == null) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
var currentNode = _tree; |
|||
|
|||
while (currentNode != null) |
|||
{ |
|||
var nodeResult = _comparer.Compare(item, currentNode.Data); |
|||
|
|||
if (nodeResult == 0) |
|||
{ |
|||
return currentNode; |
|||
} |
|||
|
|||
currentNode = nodeResult < 0 ? currentNode.Left : currentNode.Right; |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Finds the node that matches the custom delegate.
|
|||
/// </summary>
|
|||
/// <typeparam name="TSearch">The type of the search.</typeparam>
|
|||
/// <param name="value">The value.</param>
|
|||
/// <param name="customComparison">The custom comparison.</param>
|
|||
/// <returns>The item if found, else null.</returns>
|
|||
protected virtual BinaryTree<T> FindNode<TSearch>(TSearch value, CustomComparison<TSearch> customComparison) |
|||
{ |
|||
if (_tree == null) |
|||
{ |
|||
return null; |
|||
} |
|||
|
|||
var currentNode = _tree; |
|||
|
|||
while (currentNode != null) |
|||
{ |
|||
var nodeResult = customComparison(value, currentNode.Data); |
|||
|
|||
if (nodeResult == 0) |
|||
{ |
|||
return currentNode; |
|||
} |
|||
|
|||
currentNode = nodeResult < 0 ? currentNode.Left : currentNode.Right; |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Removes the item from the tree.
|
|||
/// </summary>
|
|||
/// <param name="item">The item to remove.</param>
|
|||
/// <returns>An indication of whether the item has been removed from the tree.</returns>
|
|||
protected abstract bool RemoveItem(T item); |
|||
|
|||
/// <summary>
|
|||
/// Adds the item.
|
|||
/// </summary>
|
|||
/// <param name="item">The item.</param>
|
|||
protected abstract void AddItem(T item); |
|||
|
|||
|
|||
/// <summary>
|
|||
/// Find the maximum node.
|
|||
/// </summary>
|
|||
/// <returns>The maximum node.</returns>
|
|||
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")] |
|||
protected BinaryTree<T> FindMaximumNode() |
|||
{ |
|||
#region Debug
|
|||
|
|||
Debug.Assert(_tree != null); |
|||
|
|||
#endregion
|
|||
|
|||
return FindMaximumNode(_tree); |
|||
} |
|||
|
|||
|
|||
/// <summary>
|
|||
/// Find the minimum node.
|
|||
/// </summary>
|
|||
/// <returns>The minimum node.</returns>
|
|||
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")] |
|||
protected BinaryTree<T> FindMinimumNode() |
|||
{ |
|||
#region Debug
|
|||
|
|||
Debug.Assert(_tree != null); |
|||
|
|||
#endregion
|
|||
|
|||
return FindMinimumNode(_tree); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Finds the maximum node.
|
|||
/// </summary>
|
|||
/// <param name="startNode">The start node.</param>
|
|||
/// <returns>The maximum node below this node.</returns>
|
|||
[SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")] |
|||
protected static BinaryTree<T> FindMaximumNode(BinaryTree<T> startNode) |
|||
{ |
|||
#region Asserts
|
|||
|
|||
Debug.Assert(startNode != null); |
|||
|
|||
#endregion
|
|||
|
|||
var searchNode = startNode; |
|||
|
|||
while (searchNode.Right != null) |
|||
{ |
|||
searchNode = searchNode.Right; |
|||
} |
|||
|
|||
return searchNode; |
|||
} |
|||
|
|||
|
|||
/// <summary>
|
|||
/// Finds the minimum node.
|
|||
/// </summary>
|
|||
/// <param name="startNode">The start node.</param>
|
|||
/// <returns>The minimum node below this node.</returns>
|
|||
[SuppressMessage("Microsoft.Design", "CA1000:DoNotDeclareStaticMembersOnGenericTypes")] |
|||
protected static BinaryTree<T> FindMinimumNode(BinaryTree<T> startNode) |
|||
{ |
|||
#region Asserts
|
|||
|
|||
Debug.Assert(startNode != null); |
|||
|
|||
#endregion
|
|||
|
|||
var searchNode = startNode; |
|||
|
|||
while (searchNode.Left != null) |
|||
{ |
|||
searchNode = searchNode.Left; |
|||
} |
|||
|
|||
return searchNode; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the <see cref="BinaryTree{T}"/> for this <see cref="BinarySearchTreeBase{TKey,TValue}"/>.
|
|||
/// </summary>
|
|||
[SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] |
|||
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")] |
|||
protected BinaryTree<T> Tree |
|||
{ |
|||
get |
|||
{ |
|||
return _tree; |
|||
} |
|||
set |
|||
{ |
|||
_tree = value; |
|||
} |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region Private Members
|
|||
|
|||
/// <summary>
|
|||
/// Visits the node in an in-order fashion.
|
|||
/// </summary>
|
|||
/// <param name="node">The node.</param>
|
|||
/// <param name="visitor">The visitor.</param>
|
|||
private static void VisitNode(BinaryTree<T> node, OrderedVisitor<T> visitor) |
|||
{ |
|||
if (node != null) |
|||
{ |
|||
var pair = node.Data; |
|||
|
|||
visitor.VisitPreOrder(pair); |
|||
|
|||
VisitNode(node.Left, visitor); |
|||
|
|||
visitor.VisitInOrder(pair); |
|||
|
|||
VisitNode(node.Right, visitor); |
|||
|
|||
visitor.VisitPostOrder(pair); |
|||
} |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region ISearchTree<TKey,TValue> Members
|
|||
|
|||
/// <inheritdoc />
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Trees\BinarySearchTreeBaseExamples.cs" region="Minimum" lang="cs" title="The following example shows how to use the Minimum property."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Trees\BinarySearchTreeBaseExamples.vb" region="Minimum" lang="vbnet" title="The following example shows how to use the Minimum property."/>
|
|||
/// </example>
|
|||
public virtual T Minimum |
|||
{ |
|||
get |
|||
{ |
|||
#region Validation
|
|||
|
|||
ValidateEmpty(); |
|||
|
|||
#endregion
|
|||
|
|||
return FindMinimumNode().Data; |
|||
} |
|||
} |
|||
|
|||
private void ValidateEmpty() |
|||
{ |
|||
if (Count == 0) |
|||
{ |
|||
throw new InvalidOperationException("The search tree is empty."); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Trees\BinarySearchTreeBaseExamples.cs" region="Maximum" lang="cs" title="The following example shows how to use the Maximum property."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Trees\BinarySearchTreeBaseExamples.vb" region="Maximum" lang="vbnet" title="The following example shows how to use the Maximum property."/>
|
|||
/// </example>
|
|||
public virtual T Maximum |
|||
{ |
|||
get |
|||
{ |
|||
ValidateEmpty(); |
|||
|
|||
return FindMaximumNode().Data; |
|||
} |
|||
} /// <inheritdoc/>
|
|||
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")] |
|||
public void DepthFirstTraversal(OrderedVisitor<T> visitor) |
|||
{ |
|||
Guard.ArgumentNotNull(visitor, "visitor"); |
|||
|
|||
VisitNode(_tree, visitor); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")] |
|||
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")] |
|||
public IEnumerator<T> GetOrderedEnumerator() |
|||
{ |
|||
if (_tree != null) |
|||
{ |
|||
var trackingVisitor = new TrackingVisitor<T>(); |
|||
var inOrderVisitor = new InOrderVisitor<T>(trackingVisitor); |
|||
|
|||
_tree.DepthFirstTraversal(inOrderVisitor); |
|||
|
|||
var trackingList = trackingVisitor.TrackingList; |
|||
|
|||
for (var i = 0; i < trackingList.Count; i++) |
|||
{ |
|||
yield return trackingList[i]; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Trees\BinarySearchTreeBaseExamples.cs" region="IsEmpty" lang="cs" title="The following example shows how to use the IsEmpty property."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Trees\BinarySearchTreeBaseExamples.vb" region="IsEmpty" lang="vbnet" title="The following example shows how to use the IsEmpty property."/>
|
|||
/// </example>
|
|||
public bool IsEmpty => Count == 0; |
|||
|
|||
/// <inheritdoc />
|
|||
public bool Remove(T item) |
|||
{ |
|||
var itemRemoved = RemoveItem(item); |
|||
|
|||
if (itemRemoved) |
|||
{ |
|||
Count--; |
|||
} |
|||
|
|||
return itemRemoved; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Trees\BinarySearchTreeBaseExamples.cs" region="Clear" lang="cs" title="The following example shows how to use the Clear method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Trees\BinarySearchTreeBaseExamples.vb" region="Clear" lang="vbnet" title="The following example shows how to use the Clear method."/>
|
|||
/// </example>
|
|||
public void Clear() |
|||
{ |
|||
ClearItems(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Clears all the objects in this instance.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// <b>Notes to Inheritors: </b>
|
|||
/// Derived classes can override this method to change the behavior of the <see cref="Clear"/> method.
|
|||
/// </remarks>
|
|||
protected virtual void ClearItems() |
|||
{ |
|||
_tree = null; |
|||
Count = 0; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Trees\BinarySearchTreeBaseExamples.cs" region="Count" lang="cs" title="The following example shows how to use the Count property."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Trees\BinarySearchTreeBaseExamples.vb" region="Count" lang="vbnet" title="The following example shows how to use the Count property."/>
|
|||
/// </example>
|
|||
public int Count { get; private set; } |
|||
|
|||
#endregion
|
|||
|
|||
#region IEnumerable Members
|
|||
|
|||
/// <inheritdoc />
|
|||
IEnumerator IEnumerable.GetEnumerator() |
|||
{ |
|||
return GetEnumerator(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns an enumerator that iterates through the collection.
|
|||
/// </summary>
|
|||
/// <returns>
|
|||
/// A <see cref="IEnumerator{T}"/> that can be used to iterate through the collection.
|
|||
/// </returns>
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Trees\BinarySearchTreeBaseExamples.cs" region="GetEnumerator" lang="cs" title="The following example shows how to use the GetEnumerator method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Trees\BinarySearchTreeBaseExamples.vb" region="GetEnumerator" lang="vbnet" title="The following example shows how to use the GetEnumerator method."/>
|
|||
/// </example>
|
|||
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")] |
|||
public IEnumerator<T> GetEnumerator() |
|||
{ |
|||
if (_tree != null) |
|||
{ |
|||
var stack = new Stack<BinaryTree<T>>(); |
|||
|
|||
stack.Push(_tree); |
|||
|
|||
while (stack.Count > 0) |
|||
{ |
|||
var binaryTree = stack.Pop(); |
|||
|
|||
yield return binaryTree.Data; |
|||
|
|||
if (binaryTree.Left != null) |
|||
{ |
|||
stack.Push(binaryTree.Left); |
|||
} |
|||
|
|||
if (binaryTree.Right != null) |
|||
{ |
|||
stack.Push(binaryTree.Right); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
|
|||
#region ICollection<T> Members
|
|||
|
|||
/// <inheritdoc />
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Trees\BinarySearchTreeBaseExamples.cs" region="AddKeyValuePair" lang="cs" title="The following example shows how to use the AddKeyValuePair method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Trees\BinarySearchTreeBaseExamples.vb" region="AddKeyValuePair" lang="vbnet" title="The following example shows how to use the AddKeyValuePair method."/>
|
|||
/// </example>
|
|||
public void Add(T item) |
|||
{ |
|||
AddItem(item); |
|||
Count++; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Trees\BinarySearchTreeBaseExamples.cs" region="Contains" lang="cs" title="The following example shows how to use the Contains method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Trees\BinarySearchTreeBaseExamples.vb" region="Contains" lang="vbnet" title="The following example shows how to use the Contains method."/>
|
|||
/// </example>
|
|||
public virtual bool Contains(T item) |
|||
{ |
|||
var node = FindNode(item); |
|||
return node != null; |
|||
} |
|||
|
|||
|
|||
/// <inheritdoc />
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Trees\BinarySearchTreeBaseExamples.cs" region="CopyTo" lang="cs" title="The following example shows how to use the CopyTo method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Trees\BinarySearchTreeBaseExamples.vb" region="CopyTo" lang="vbnet" title="The following example shows how to use the CopyTo method."/>
|
|||
/// </example>
|
|||
public void CopyTo(T[] array, int arrayIndex) |
|||
{ |
|||
#region Validation
|
|||
|
|||
Guard.ArgumentNotNull(array, "array"); |
|||
|
|||
if ((array.Length - arrayIndex) < Count) |
|||
{ |
|||
throw new ArgumentException(Constants.NotEnoughSpaceInTheTargetArray, "array"); |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
foreach (var association in _tree) |
|||
{ |
|||
array[arrayIndex++] = association; |
|||
} |
|||
} |
|||
/// <inheritdoc />
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Trees\BinarySearchTreeBaseExamples.cs" region="IsReadOnly" lang="cs" title="The following example shows how to use the IsReadOnly property."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Trees\BinarySearchTreeBaseExamples.vb" region="IsReadOnly" lang="vbnet" title="The following example shows how to use the IsReadOnly property."/>
|
|||
/// </example>
|
|||
public bool IsReadOnly => false; |
|||
|
|||
#endregion
|
|||
} |
|||
} |
|||
@ -1,674 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
/* |
|||
Copyright 2007-2013 The NGenerics Team |
|||
(https://github.com/ngenerics/ngenerics/wiki/Team)
|
|||
|
|||
This program is licensed under the GNU Lesser General Public License (LGPL). You should |
|||
have received a copy of the license along with the source code. If not, an online copy |
|||
of the license can be found at http://www.gnu.org/copyleft/lesser.html.
|
|||
*/ |
|||
|
|||
|
|||
using System; |
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
using NGenerics.Patterns.Visitor; |
|||
using NGenerics.Util; |
|||
using System.Diagnostics.CodeAnalysis; |
|||
|
|||
namespace NGenerics.DataStructures.Trees |
|||
{ |
|||
/// <summary>
|
|||
/// An implementation of a Binary Tree data structure.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The type of elements in the <see cref="BinaryTree{T}"/>.</typeparam>
|
|||
//[Serializable]
|
|||
[SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")] |
|||
public class BinaryTree<T> : ICollection<T>, ITree<T> |
|||
{ |
|||
#region Globals
|
|||
|
|||
private BinaryTree<T> _leftSubtree; |
|||
private BinaryTree<T> _rightSubtree; |
|||
private T _data; |
|||
|
|||
#endregion
|
|||
|
|||
#region Construction
|
|||
|
|||
/// <param name="data">The data contained in this node.</param>
|
|||
public BinaryTree(T data) : this(data, null, null) { } |
|||
|
|||
/// <param name="data">The data.</param>
|
|||
/// <param name="left">The data of the left subtree.</param>
|
|||
/// <param name="right">The data of the right subtree.</param>
|
|||
public BinaryTree(T data, T left, T right) : this(data, new BinaryTree<T>(left), new BinaryTree<T>(right)) { } |
|||
|
|||
/// <param name="data">The data contained in this node.</param>
|
|||
/// <param name="left">The left subtree.</param>
|
|||
/// <param name="right">The right subtree.</param>
|
|||
public BinaryTree(T data, BinaryTree<T> left, BinaryTree<T> right) |
|||
: this(data, left, right, true) |
|||
{ |
|||
} |
|||
|
|||
|
|||
|
|||
/// <param name="data">The data contained in this node.</param>
|
|||
/// <param name="left">The left subtree.</param>
|
|||
/// <param name="right">The right subtree.</param>
|
|||
/// <param name="validateData"><see langword="true"/> to validate <paramref name="data"/>; otherwise <see langword="false"/>.</param>
|
|||
internal BinaryTree(T data, BinaryTree<T> left, BinaryTree<T> right, bool validateData) |
|||
{ |
|||
#region Validation
|
|||
|
|||
//TODO: probably not the most efficient way of doing this but SplayTree needs to use a BinaryTree with null data.
|
|||
if (validateData) |
|||
{ |
|||
Guard.ArgumentNotNull(data, "data"); |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
_leftSubtree = left; |
|||
|
|||
if (left != null) |
|||
{ |
|||
left.Parent = this; |
|||
} |
|||
|
|||
_rightSubtree = right; |
|||
|
|||
if (right != null) |
|||
{ |
|||
right.Parent = this; |
|||
} |
|||
|
|||
_data = data; |
|||
} |
|||
|
|||
|
|||
|
|||
#endregion
|
|||
|
|||
#region ICollection<T> Members
|
|||
|
|||
/// <inheritdoc />
|
|||
public bool IsEmpty => Count == 0; |
|||
|
|||
/// <inheritdoc />
|
|||
public bool IsFull => (_leftSubtree != null) && (_rightSubtree != null); |
|||
|
|||
/// <inheritdoc />
|
|||
public bool Contains(T item) |
|||
{ |
|||
foreach (var thisItem in this) |
|||
{ |
|||
if (item.Equals(thisItem)) |
|||
{ |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void CopyTo(T[] array, int arrayIndex) |
|||
{ |
|||
Guard.ArgumentNotNull(array, "array"); |
|||
|
|||
foreach (var item in this) |
|||
{ |
|||
#region Validation
|
|||
|
|||
if (arrayIndex >= array.Length) |
|||
{ |
|||
throw new ArgumentException(Constants.NotEnoughSpaceInTheTargetArray, "array"); |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
array[arrayIndex++] = item; |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public int Count |
|||
{ |
|||
get |
|||
{ |
|||
var count = 0; |
|||
|
|||
if (_leftSubtree != null) |
|||
{ |
|||
count++; |
|||
} |
|||
|
|||
if (_rightSubtree != null) |
|||
{ |
|||
count++; |
|||
} |
|||
|
|||
return count; |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public void Add(T item) |
|||
{ |
|||
AddItem(new BinaryTree<T>(item)); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public bool Remove(T item) |
|||
{ |
|||
if (_leftSubtree != null) |
|||
{ |
|||
if (_leftSubtree._data.Equals(item)) |
|||
{ |
|||
RemoveLeft(); |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
if (_rightSubtree != null) |
|||
{ |
|||
if (_rightSubtree._data.Equals(item)) |
|||
{ |
|||
RemoveRight(); |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Removes the specified child.
|
|||
/// </summary>
|
|||
/// <param name="child">The child.</param>
|
|||
/// <returns>A value indicating whether the child was found (and removed) from this tree.</returns>
|
|||
public bool Remove(BinaryTree<T> child) |
|||
{ |
|||
if (_leftSubtree != null) |
|||
{ |
|||
if (_leftSubtree == child) |
|||
{ |
|||
RemoveLeft(); |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
if (_rightSubtree != null) |
|||
{ |
|||
if (_rightSubtree == child) |
|||
{ |
|||
RemoveRight(); |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns an enumerator that iterates through the collection.
|
|||
/// </summary>
|
|||
/// <returns>
|
|||
/// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.
|
|||
/// </returns>
|
|||
public IEnumerator<T> GetEnumerator() |
|||
{ |
|||
var stack = new Stack<BinaryTree<T>>(); |
|||
|
|||
stack.Push(this); |
|||
|
|||
while (stack.Count > 0) |
|||
{ |
|||
var tree = stack.Pop(); |
|||
|
|||
yield return tree.Data; |
|||
|
|||
if (tree._leftSubtree != null) |
|||
{ |
|||
stack.Push(tree._leftSubtree); |
|||
} |
|||
|
|||
if (tree._rightSubtree != null) |
|||
{ |
|||
stack.Push(tree._rightSubtree); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public virtual void Clear() |
|||
{ |
|||
if (_leftSubtree != null) |
|||
{ |
|||
_leftSubtree.Parent = null; |
|||
_leftSubtree = null; |
|||
} |
|||
|
|||
if (_rightSubtree != null) |
|||
{ |
|||
_rightSubtree.Parent = null; |
|||
_rightSubtree = null; |
|||
} |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region ITree<T> Members
|
|||
|
|||
/// <inheritdoc />
|
|||
void ITree<T>.Add(ITree<T> child) |
|||
{ |
|||
AddItem((BinaryTree<T>)child); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
ITree<T> ITree<T>.GetChild(int index) |
|||
{ |
|||
return GetChild(index); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
bool ITree<T>.Remove(ITree<T> child) |
|||
{ |
|||
return Remove((BinaryTree<T>)child); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
ITree<T> ITree<T>.FindNode(Predicate<T> condition) |
|||
{ |
|||
return FindNode(condition); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
ITree<T> ITree<T>.Parent => Parent; |
|||
|
|||
#endregion
|
|||
|
|||
#region Public Members
|
|||
|
|||
/// <summary>
|
|||
/// Gets the parent of the current node..
|
|||
/// </summary>
|
|||
/// <value>The parent of the current node.</value>
|
|||
public BinaryTree<T> Parent { get; private set; } |
|||
|
|||
/// <summary>
|
|||
/// Finds the node with the specified condition. If a node is not found matching
|
|||
/// the specified condition, null is returned.
|
|||
/// </summary>
|
|||
/// <param name="condition">The condition to test.</param>
|
|||
/// <returns>The first node that matches the condition supplied. If a node is not found, null is returned.</returns>
|
|||
/// <exception cref="ArgumentNullException"><paramref name="condition"/> is a null reference (<c>Nothing</c> in Visual Basic).</exception>
|
|||
public BinaryTree<T> FindNode(Predicate<T> condition) |
|||
{ |
|||
Guard.ArgumentNotNull(condition, "condition"); |
|||
|
|||
if (condition(Data)) |
|||
{ |
|||
return this; |
|||
} |
|||
|
|||
if (_leftSubtree != null) |
|||
{ |
|||
var ret = _leftSubtree.FindNode(condition); |
|||
|
|||
if (ret != null) |
|||
{ |
|||
return ret; |
|||
} |
|||
} |
|||
|
|||
if (_rightSubtree != null) |
|||
{ |
|||
var ret = _rightSubtree.FindNode(condition); |
|||
|
|||
if (ret != null) |
|||
{ |
|||
return ret; |
|||
} |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the left subtree.
|
|||
/// </summary>
|
|||
/// <value>The left subtree.</value>
|
|||
[SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] |
|||
public virtual BinaryTree<T> Left |
|||
{ |
|||
get |
|||
{ |
|||
return _leftSubtree; |
|||
} |
|||
set |
|||
{ |
|||
if (_leftSubtree != null) |
|||
{ |
|||
RemoveLeft(); |
|||
} |
|||
|
|||
if (value != null) |
|||
{ |
|||
if (value.Parent != null) |
|||
{ |
|||
value.Parent.Remove(value); |
|||
} |
|||
|
|||
value.Parent = this; |
|||
} |
|||
|
|||
_leftSubtree = value; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the right subtree.
|
|||
/// </summary>
|
|||
/// <value>The right subtree.</value>
|
|||
[SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] |
|||
public virtual BinaryTree<T> Right |
|||
{ |
|||
get |
|||
{ |
|||
return _rightSubtree; |
|||
} |
|||
set |
|||
{ |
|||
if (_rightSubtree != null) |
|||
{ |
|||
RemoveRight(); |
|||
} |
|||
|
|||
if (value != null) |
|||
{ |
|||
if (value.Parent != null) |
|||
{ |
|||
value.Parent.Remove(value); |
|||
} |
|||
|
|||
value.Parent = this; |
|||
} |
|||
|
|||
_rightSubtree = value; |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public virtual T Data |
|||
{ |
|||
get |
|||
{ |
|||
return _data; |
|||
} |
|||
set |
|||
{ |
|||
#region Validation
|
|||
|
|||
Guard.ArgumentNotNull(value, "data"); |
|||
|
|||
#endregion
|
|||
|
|||
_data = value; |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public int Degree => Count; |
|||
|
|||
/// <summary>
|
|||
/// Gets the child at the specified index.
|
|||
/// </summary>
|
|||
/// <param name="index">The index of the child in question.</param>
|
|||
/// <returns>The child at the specified index.</returns>
|
|||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> does not equal 0 or 1.</exception>
|
|||
public BinaryTree<T> GetChild(int index) |
|||
{ |
|||
switch (index) |
|||
{ |
|||
case 0: |
|||
return _leftSubtree; |
|||
case 1: |
|||
return _rightSubtree; |
|||
default: |
|||
throw new ArgumentOutOfRangeException("index"); |
|||
} |
|||
} |
|||
/// <inheritdoc />
|
|||
public virtual int Height |
|||
{ |
|||
get |
|||
{ |
|||
if (Degree == 0) |
|||
{ |
|||
return 0; |
|||
} |
|||
|
|||
return 1 + FindMaximumChildHeight(); |
|||
} |
|||
} |
|||
|
|||
|
|||
/// <summary>
|
|||
/// Performs a depth first traversal on this tree with the specified visitor.
|
|||
/// </summary>
|
|||
/// <param name="orderedVisitor">The ordered visitor.</param>
|
|||
/// <exception cref="ArgumentNullException"><paramref name="orderedVisitor"/> is a null reference (<c>Nothing</c> in Visual Basic).</exception>
|
|||
public virtual void DepthFirstTraversal(OrderedVisitor<T> orderedVisitor) |
|||
{ |
|||
Guard.ArgumentNotNull(orderedVisitor, "orderedVisitor"); |
|||
|
|||
if (orderedVisitor.HasCompleted) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
// Preorder visit
|
|||
orderedVisitor.VisitPreOrder(Data); |
|||
|
|||
if (_leftSubtree != null) |
|||
{ |
|||
_leftSubtree.DepthFirstTraversal(orderedVisitor); |
|||
} |
|||
|
|||
// In-order visit
|
|||
orderedVisitor.VisitInOrder(_data); |
|||
|
|||
if (_rightSubtree != null) |
|||
{ |
|||
_rightSubtree.DepthFirstTraversal(orderedVisitor); |
|||
} |
|||
|
|||
// PostOrder visit
|
|||
orderedVisitor.VisitPostOrder(Data); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs a breadth first traversal on this tree with the specified visitor.
|
|||
/// </summary>
|
|||
/// <param name="visitor">The visitor.</param>
|
|||
/// <exception cref="ArgumentNullException"><paramref name="visitor"/> is a null reference (<c>Nothing</c> in Visual Basic).</exception>
|
|||
public virtual void BreadthFirstTraversal(IVisitor<T> visitor) |
|||
{ |
|||
Guard.ArgumentNotNull(visitor, "visitor"); |
|||
|
|||
var queue = new Queue<BinaryTree<T>>(); |
|||
|
|||
queue.Enqueue(this); |
|||
|
|||
while (queue.Count > 0) |
|||
{ |
|||
if (visitor.HasCompleted) |
|||
{ |
|||
break; |
|||
} |
|||
|
|||
var binaryTree = queue.Dequeue(); |
|||
visitor.Visit(binaryTree.Data); |
|||
|
|||
for (var i = 0; i < binaryTree.Degree; i++) |
|||
{ |
|||
var child = binaryTree.GetChild(i); |
|||
|
|||
if (child != null) |
|||
{ |
|||
queue.Enqueue(child); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
|
|||
/// <inheritdoc />
|
|||
public virtual bool IsLeafNode => Degree == 0; |
|||
|
|||
/// <summary>
|
|||
/// Removes the left child.
|
|||
/// </summary>
|
|||
public virtual void RemoveLeft() |
|||
{ |
|||
if (_leftSubtree != null) |
|||
{ |
|||
_leftSubtree.Parent = null; |
|||
_leftSubtree = null; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Removes the left child.
|
|||
/// </summary>
|
|||
public virtual void RemoveRight() |
|||
{ |
|||
if (_rightSubtree != null) |
|||
{ |
|||
_rightSubtree.Parent = null; |
|||
_rightSubtree = null; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adds an item to the <see cref="ICollection{T}"/>.
|
|||
/// </summary>
|
|||
/// <param name="subtree">The subtree.</param>
|
|||
/// <exception cref="NotSupportedException">The <see cref="ICollection{T}"/> is read-only.</exception>
|
|||
/// <exception cref="InvalidOperationException">The <see cref="BinaryTree{T}"/> is full.</exception>
|
|||
/// <exception cref="ArgumentNullException"><paramref name="subtree"/> is null (Nothing in Visual Basic).</exception>
|
|||
public void Add(BinaryTree<T> subtree) |
|||
{ |
|||
Guard.ArgumentNotNull(subtree, "subtree"); |
|||
|
|||
AddItem(subtree); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adds an item to the <see cref="ICollection{T}"/>.
|
|||
/// </summary>
|
|||
/// <param name="subtree">The subtree.</param>
|
|||
/// <remarks>
|
|||
/// <b>Notes to Inheritors: </b>
|
|||
/// Derived classes can override this method to change the behavior of the <see cref="Clear"/> method.
|
|||
/// </remarks>
|
|||
protected virtual void AddItem(BinaryTree<T> subtree) |
|||
{ |
|||
if (_leftSubtree == null) |
|||
{ |
|||
if (subtree.Parent != null) |
|||
{ |
|||
subtree.Parent.Remove(subtree); |
|||
} |
|||
|
|||
_leftSubtree = subtree; |
|||
subtree.Parent = this; |
|||
} |
|||
else if (_rightSubtree == null) |
|||
{ |
|||
if (subtree.Parent != null) |
|||
{ |
|||
subtree.Parent.Remove(subtree); |
|||
} |
|||
|
|||
_rightSubtree = subtree; |
|||
subtree.Parent = this; |
|||
} |
|||
else |
|||
{ |
|||
throw new InvalidOperationException("This binary tree is full."); |
|||
} |
|||
} |
|||
|
|||
|
|||
#endregion
|
|||
|
|||
#region Private Members
|
|||
|
|||
/// <summary>
|
|||
/// Finds the maximum height between the child nodes.
|
|||
/// </summary>
|
|||
/// <returns>The maximum height of the tree between all paths from this node and all leaf nodes.</returns>
|
|||
protected virtual int FindMaximumChildHeight() |
|||
{ |
|||
var leftHeight = 0; |
|||
var rightHeight = 0; |
|||
|
|||
if (_leftSubtree != null) |
|||
{ |
|||
leftHeight = _leftSubtree.Height; |
|||
} |
|||
|
|||
if (_rightSubtree != null) |
|||
{ |
|||
rightHeight = _rightSubtree.Height; |
|||
} |
|||
|
|||
return leftHeight > rightHeight ? leftHeight : rightHeight; |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region Operator Overloads
|
|||
|
|||
/// <summary>
|
|||
/// Gets the <see cref="BinaryTree{T}"/> at the specified index.
|
|||
/// </summary>
|
|||
public BinaryTree<T> this[int index] => GetChild(index); |
|||
|
|||
#endregion
|
|||
|
|||
#region ICollection<T> Members
|
|||
|
|||
/// <inheritdoc />
|
|||
public bool IsReadOnly => false; |
|||
|
|||
#endregion
|
|||
|
|||
#region IEnumerable Members
|
|||
|
|||
/// <inheritdoc />
|
|||
IEnumerator IEnumerable.GetEnumerator() |
|||
{ |
|||
return GetEnumerator(); |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region Object Members
|
|||
|
|||
/// <inheritdoc />
|
|||
public override string ToString() |
|||
{ |
|||
return _data.ToString(); |
|||
} |
|||
|
|||
#endregion
|
|||
} |
|||
} |
|||
@ -1,68 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
/* |
|||
Copyright 2007-2013 The NGenerics Team |
|||
(https://github.com/ngenerics/ngenerics/wiki/Team)
|
|||
|
|||
This program is licensed under the GNU Lesser General Public License (LGPL). You should |
|||
have received a copy of the license along with the source code. If not, an online copy |
|||
of the license can be found at http://www.gnu.org/copyleft/lesser.html.
|
|||
*/ |
|||
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Diagnostics.CodeAnalysis; |
|||
using NGenerics.Patterns.Visitor; |
|||
|
|||
namespace NGenerics.DataStructures.Trees |
|||
{ |
|||
/// <summary>
|
|||
/// An interface for Search Trees that mimic a dictionary.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The type of element to hold in the tree.</typeparam>
|
|||
[SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")] |
|||
public interface ISearchTree<T> : ICollection<T> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the largest item in the tree.
|
|||
/// </summary>
|
|||
/// <value>The largest item in the tree.</value>
|
|||
/// <exception cref="InvalidOperationException">The <see cref="ISearchTree{T}"/> is empty.</exception>
|
|||
T Maximum { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the smallest item in the tree.
|
|||
/// </summary>
|
|||
/// <value>The smallest item in the tree.</value>
|
|||
/// <exception cref="InvalidOperationException">The <see cref="ISearchTree{T}"/> is empty.</exception>
|
|||
T Minimum { get; } |
|||
|
|||
/// <summary>
|
|||
/// Performs a depth first traversal on the search tree.
|
|||
/// </summary>
|
|||
/// <param name="visitor">The visitor to use.</param>
|
|||
/// <exception cref="ArgumentNullException"><paramref name="visitor"/> is a null reference (<c>Nothing</c> in Visual Basic).</exception>
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Trees\BinarySearchTreeBaseExamples.cs" region="DepthFirstTraversal" lang="cs" title="The following example shows how to use the DepthFirstTraversal method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Trees\BinarySearchTreeBaseExamples.vb" region="DepthFirstTraversal" lang="vbnet" title="The following example shows how to use the DepthFirstTraversal method."/>
|
|||
/// </example>
|
|||
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")] |
|||
void DepthFirstTraversal(OrderedVisitor<T> visitor); |
|||
|
|||
/// <summary>
|
|||
/// Returns an enumerator that iterates through the collection.
|
|||
/// </summary>
|
|||
/// <returns>
|
|||
/// A <see cref="IEnumerator{T}"/> that can be used to iterate through the collection.
|
|||
/// </returns>
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Trees\BinarySearchTreeBaseExamples.cs" region="GetOrderedEnumerator" lang="cs" title="The following example shows how to use the GetOrderedEnumerator method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Trees\BinarySearchTreeBaseExamples.vb" region="GetOrderedEnumerator" lang="vbnet" title="The following example shows how to use the GetOrderedEnumerator method."/>
|
|||
/// </example>
|
|||
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")] |
|||
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")] |
|||
IEnumerator<T> GetOrderedEnumerator(); |
|||
} |
|||
} |
|||
@ -1,82 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
/* |
|||
Copyright 2007-2013 The NGenerics Team |
|||
(https://github.com/ngenerics/ngenerics/wiki/Team)
|
|||
|
|||
This program is licensed under the GNU Lesser General Public License (LGPL). You should |
|||
have received a copy of the license along with the source code. If not, an online copy |
|||
of the license can be found at http://www.gnu.org/copyleft/lesser.html.
|
|||
*/ |
|||
|
|||
using System; |
|||
|
|||
namespace NGenerics.DataStructures.Trees |
|||
{ |
|||
/// <summary>
|
|||
/// An interface for the tree data structure
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The type of elements in the tree.</typeparam>
|
|||
public interface ITree<T> |
|||
{ |
|||
/// <summary>
|
|||
/// Adds the specified child to the tree.
|
|||
/// </summary>
|
|||
/// <param name="child">The child to add..</param>
|
|||
void Add(ITree<T> child); |
|||
|
|||
/// <summary>
|
|||
/// Gets the data held in this node.
|
|||
/// </summary>
|
|||
/// <value>The data.</value>
|
|||
T Data { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the degree of this node.
|
|||
/// </summary>
|
|||
/// <value>The degree of this node.</value>
|
|||
int Degree { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the child at the specified index.
|
|||
/// </summary>
|
|||
/// <param name="index">The index.</param>
|
|||
/// <returns>The child at the specified index.</returns>
|
|||
ITree<T> GetChild(int index); |
|||
|
|||
/// <summary>
|
|||
/// Gets the height of this tree.
|
|||
/// </summary>
|
|||
/// <value>The height of this tree.</value>
|
|||
int Height { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this instance is leaf node.
|
|||
/// </summary>
|
|||
/// <value>
|
|||
/// <c>true</c> if this instance is leaf node; otherwise, <c>false</c>.
|
|||
/// </value>
|
|||
bool IsLeafNode { get; } |
|||
|
|||
/// <summary>
|
|||
/// Removes the specified child.
|
|||
/// </summary>
|
|||
/// <param name="child">The child.</param>
|
|||
/// <returns>An indication of whether the child was found (and removed) from this tree.</returns>
|
|||
bool Remove(ITree<T> child); |
|||
|
|||
/// <summary>
|
|||
/// Finds the node for which the given predicate holds true.
|
|||
/// </summary>
|
|||
/// <param name="condition">The condition to test on the data item.</param>
|
|||
/// <returns>The fist node that matches the condition if found, otherwise null.</returns>
|
|||
ITree<T> FindNode(Predicate<T> condition); |
|||
|
|||
/// <summary>
|
|||
/// Gets the parent of the current node.
|
|||
/// </summary>
|
|||
/// <value>The parent of the current node.</value>
|
|||
ITree<T> Parent { get; } |
|||
} |
|||
} |
|||
@ -1,21 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
/* |
|||
Copyright 2007-2013 The NGenerics Team |
|||
(https://github.com/ngenerics/ngenerics/wiki/Team)
|
|||
|
|||
This program is licensed under the GNU Lesser General Public License (LGPL). You should |
|||
have received a copy of the license along with the source code. If not, an online copy |
|||
of the license can be found at http://www.gnu.org/copyleft/lesser.html.
|
|||
*/ |
|||
|
|||
|
|||
namespace NGenerics.DataStructures.Trees |
|||
{ |
|||
internal enum NodeColor |
|||
{ |
|||
Red = 0, |
|||
Black = 1 |
|||
} |
|||
} |
|||
@ -1,291 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
/* |
|||
Copyright 2007-2013 The NGenerics Team |
|||
(https://github.com/ngenerics/ngenerics/wiki/Team)
|
|||
|
|||
This program is licensed under the GNU Lesser General Public License (LGPL). You should |
|||
have received a copy of the license along with the source code. If not, an online copy |
|||
of the license can be found at http://www.gnu.org/copyleft/lesser.html.
|
|||
*/ |
|||
|
|||
|
|||
/* |
|||
* The insertion and deletion code is based on the code found at http://eternallyconfuzzled.com/tuts/redblack.htm.
|
|||
* It's an excellent tutorial - if you want to understand Red Black trees, look there first. |
|||
*/ |
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Diagnostics.CodeAnalysis; |
|||
|
|||
namespace NGenerics.DataStructures.Trees |
|||
{ |
|||
/// <summary>
|
|||
/// An implementation of a Red-Black tree.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The type of element to keep in the tree.</typeparam>
|
|||
[SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")] |
|||
//[Serializable]
|
|||
public class RedBlackTree<T> : BinarySearchTreeBase<T> |
|||
{ |
|||
#region Construction
|
|||
|
|||
/// <inheritdoc />
|
|||
public RedBlackTree() |
|||
{ |
|||
// Do nothing - the default Comparer will be used by the base class.
|
|||
} |
|||
|
|||
|
|||
/// <inheritdoc/>
|
|||
public RedBlackTree(IComparer<T> comparer) |
|||
: base(comparer) |
|||
{ |
|||
// Do nothing else.
|
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public RedBlackTree(Comparison<T> comparison) |
|||
: base(comparison) |
|||
{ |
|||
// Do nothing else.
|
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region Public Members
|
|||
|
|||
/// <summary>
|
|||
/// Adds an element with the provided key and value to the <see cref="IDictionary{TKey,TValue}"/>.
|
|||
/// </summary>
|
|||
/// <param name="item">The item.</param>
|
|||
protected override void AddItem(T item) |
|||
{ |
|||
#region Validation
|
|||
|
|||
if (Equals(item, null)) |
|||
{ |
|||
throw new ArgumentNullException("item"); |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
var root = (RedBlackTreeNode<T>)Tree; |
|||
|
|||
var newRoot = InsertNode(root, item); |
|||
newRoot.Color = NodeColor.Black; |
|||
Tree = newRoot; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Removes the element with the specified key from the <see cref="IDictionary{TKey,TValue}"/>.
|
|||
/// </summary>
|
|||
/// <param name="item">The item to remove.</param>
|
|||
/// <returns>
|
|||
/// <c>true</c> if the element is successfully removed; otherwise, <c>false</c>. This method also returns false if key was not found in the original <see cref="IDictionary{TKey,TValue}"/>.
|
|||
/// </returns>
|
|||
/// <inheritdoc/>
|
|||
protected override bool RemoveItem(T item) |
|||
{ |
|||
if (Tree != null) |
|||
{ |
|||
var startNode = new RedBlackTreeNode<T>(default(T)); |
|||
|
|||
var childNode = startNode; |
|||
startNode.Right = (RedBlackTreeNode<T>)Tree; |
|||
|
|||
RedBlackTreeNode<T> parent = null; |
|||
RedBlackTreeNode<T> foundNode = null; |
|||
|
|||
var direction = true; |
|||
|
|||
while (childNode[direction] != null) |
|||
{ |
|||
var lastDirection = direction; |
|||
|
|||
var grandParent = parent; |
|||
parent = childNode; |
|||
childNode = childNode[direction]; |
|||
|
|||
var comparisonValue = Comparer.Compare(childNode.Data, item); |
|||
|
|||
if (comparisonValue == 0) |
|||
{ |
|||
foundNode = childNode; |
|||
} |
|||
|
|||
direction = comparisonValue < 0; |
|||
|
|||
if ((IsBlack(childNode)) && (IsBlack(childNode[direction]))) |
|||
{ |
|||
if (IsRed(childNode[!direction])) |
|||
{ |
|||
parent = parent[lastDirection] = SingleRotation(childNode, direction); |
|||
} |
|||
else if (IsBlack(childNode[direction])) |
|||
{ |
|||
var sibling = parent[!lastDirection]; |
|||
|
|||
if (sibling != null) |
|||
{ |
|||
if ((IsBlack(sibling.Left)) && (IsBlack(sibling.Right))) |
|||
{ |
|||
parent.Color = NodeColor.Black; |
|||
sibling.Color = NodeColor.Red; |
|||
childNode.Color = NodeColor.Red; |
|||
} |
|||
else |
|||
{ |
|||
var parentDirection = grandParent.Right == parent; |
|||
|
|||
if (IsRed(sibling[lastDirection])) |
|||
{ |
|||
grandParent[parentDirection] = DoubleRotation(parent, lastDirection); |
|||
} |
|||
else if (IsRed(sibling[!lastDirection])) |
|||
{ |
|||
grandParent[parentDirection] = SingleRotation(parent, lastDirection); |
|||
} |
|||
|
|||
childNode.Color = grandParent[parentDirection].Color = NodeColor.Red; |
|||
grandParent[parentDirection].Left.Color = NodeColor.Black; |
|||
grandParent[parentDirection].Right.Color = NodeColor.Black; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
if (foundNode != null) |
|||
{ |
|||
foundNode.Data = childNode.Data; |
|||
parent[parent.Right == childNode] = childNode[childNode.Left == null]; |
|||
} |
|||
|
|||
Tree = startNode.Right; |
|||
|
|||
if (Tree != null) |
|||
{ |
|||
((RedBlackTreeNode<T>)Tree).Color = NodeColor.Black; |
|||
} |
|||
|
|||
if (foundNode != null) |
|||
{ |
|||
return true; |
|||
} |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region Private Members
|
|||
|
|||
/// <summary>
|
|||
/// Determines whether the specified node is red.
|
|||
/// </summary>
|
|||
/// <param name="node">The node.</param>
|
|||
/// <returns>
|
|||
/// <c>true</c> if the specified node is red; otherwise, <c>false</c>.
|
|||
/// </returns>
|
|||
private static bool IsRed(RedBlackTreeNode<T> node) |
|||
{ |
|||
return (node != null) && (node.Color == NodeColor.Red); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Determines whether the specified node is black.
|
|||
/// </summary>
|
|||
/// <param name="node">The node.</param>
|
|||
/// <returns>
|
|||
/// <c>true</c> if the specified node is black; otherwise, <c>false</c>.
|
|||
/// </returns>
|
|||
private static bool IsBlack(RedBlackTreeNode<T> node) |
|||
{ |
|||
return (node == null) || (node.Color == NodeColor.Black); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// A recursive implementation of insertion of a node into the tree.
|
|||
/// </summary>
|
|||
/// <param name="node">The start node.</param>
|
|||
/// <param name="item">The item.</param>
|
|||
/// <returns>The node created in the insertion.</returns>
|
|||
private RedBlackTreeNode<T> InsertNode(RedBlackTreeNode<T> node, T item) |
|||
{ |
|||
if (node == null) |
|||
{ |
|||
node = new RedBlackTreeNode<T>(item); |
|||
} |
|||
else if (Comparer.Compare(item, node.Data) != 0) |
|||
{ |
|||
var direction = Comparer.Compare(node.Data, item) < 0; |
|||
|
|||
node[direction] = InsertNode(node[direction], item); |
|||
|
|||
if (IsRed(node[direction])) |
|||
{ |
|||
if (IsRed(node[!direction])) |
|||
{ |
|||
node.Color = NodeColor.Red; |
|||
node.Left.Color = NodeColor.Black; |
|||
node.Right.Color = NodeColor.Black; |
|||
} |
|||
else |
|||
{ |
|||
if (IsRed(node[direction][direction])) |
|||
{ |
|||
node = SingleRotation(node, !direction); |
|||
} |
|||
else if (IsRed(node[direction][!direction])) |
|||
{ |
|||
node = DoubleRotation(node, !direction); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
else |
|||
{ |
|||
throw new ArgumentException(alreadyContainedInTheTree); |
|||
} |
|||
|
|||
return node; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Perform a single rotation on the node provided..
|
|||
/// </summary>
|
|||
/// <param name="node">The node on which to focus the rotation.</param>
|
|||
/// <param name="direction">The direction of the rotation. If direction is equal to true, a right rotation is performed. Other wise, a left rotation.</param>
|
|||
/// <returns>The new root of the cluster.</returns>
|
|||
private static RedBlackTreeNode<T> SingleRotation(RedBlackTreeNode<T> node, bool direction) |
|||
{ |
|||
var childSibling = node[!direction]; |
|||
|
|||
node[!direction] = childSibling[direction]; |
|||
childSibling[direction] = node; |
|||
|
|||
node.Color = NodeColor.Red; |
|||
childSibling.Color = NodeColor.Black; |
|||
|
|||
return childSibling; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Perform a double rotation on the node provided..
|
|||
/// </summary>
|
|||
/// <param name="node">The node on which to focus the rotation.</param>
|
|||
/// <param name="direction">The direction of the rotation. If direction is equal to true, a right rotation is performed. Other wise, a left rotation.</param>
|
|||
/// <returns>The new root of the cluster.</returns>
|
|||
private static RedBlackTreeNode<T> DoubleRotation(RedBlackTreeNode<T> node, bool direction) |
|||
{ |
|||
node[!direction] = SingleRotation(node[!direction], !direction); |
|||
return SingleRotation(node, direction); |
|||
} |
|||
|
|||
#endregion
|
|||
} |
|||
} |
|||
@ -1,251 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
/* |
|||
Copyright 2007-2013 The NGenerics Team |
|||
(https://github.com/ngenerics/ngenerics/wiki/Team)
|
|||
|
|||
This program is licensed under the GNU Lesser General Public License (LGPL). You should |
|||
have received a copy of the license along with the source code. If not, an online copy |
|||
of the license can be found at http://www.gnu.org/copyleft/lesser.html.
|
|||
*/ |
|||
|
|||
|
|||
/* |
|||
* The insertion and deletion code is based on the code found at http://eternallyconfuzzled.com/tuts/redblack.htm.
|
|||
* It's an excellent tutorial - if you want to understand Red Black trees, look there first. |
|||
*/ |
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Collections.ObjectModel; |
|||
using System.Diagnostics.CodeAnalysis; |
|||
using NGenerics.Comparers; |
|||
using NGenerics.Patterns.Visitor; |
|||
|
|||
namespace NGenerics.DataStructures.Trees |
|||
{ |
|||
/// <summary>
|
|||
/// An implementation of a Red-Black tree.
|
|||
/// </summary>
|
|||
/// <typeparam name="TKey">The type of the keys in the <see cref="RedBlackTree{TKey,TValue}"/>.</typeparam>
|
|||
/// <typeparam name="TValue">The type of the values in the <see cref="RedBlackTree{TKey,TValue}"/>.</typeparam>
|
|||
[SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")] |
|||
#if (!SILVERLIGHT && !WINDOWSPHONE)
|
|||
//[Serializable]
|
|||
#endif
|
|||
public class RedBlackTree<TKey, TValue> : RedBlackTree<KeyValuePair<TKey, TValue>>, IDictionary<TKey, TValue> // BinarySearchTreeBase<TKey, TValue>
|
|||
{ |
|||
#region Construction
|
|||
/// <inheritdoc />
|
|||
public RedBlackTree() : base(new KeyValuePairComparer<TKey, TValue>()) |
|||
{ |
|||
// Do nothing - the default Comparer will be used by the base class.
|
|||
} |
|||
|
|||
|
|||
/// <inheritdoc/>
|
|||
public RedBlackTree(IComparer<TKey> comparer) |
|||
: base(new KeyValuePairComparer<TKey, TValue>(comparer)) |
|||
{ |
|||
// Do nothing else.
|
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public RedBlackTree(Comparison<TKey> comparison) |
|||
: base(new KeyValuePairComparer<TKey, TValue>(comparison)) |
|||
{ |
|||
// Do nothing else.
|
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region Private Members
|
|||
|
|||
private RedBlackTreeNode<KeyValuePair<TKey, TValue>> FindNode(TKey key) |
|||
{ |
|||
return base.FindNode(new KeyValuePair<TKey, TValue>(key, default(TValue))) as RedBlackTreeNode<KeyValuePair<TKey, TValue>>; |
|||
} |
|||
|
|||
private bool Contains(KeyValuePair<TKey, TValue> item, bool checkValue) |
|||
{ |
|||
var node = FindNode(item); |
|||
|
|||
if ((node != null) && !checkValue) |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
return node != null && Equals(item.Value, node.Data.Value); |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region IDictionary<TKey,TValue> Members
|
|||
|
|||
/// <summary>
|
|||
/// Removes the element with the specified key from the <see cref="T:System.Collections.Generic.IDictionary`2"/>.
|
|||
/// </summary>
|
|||
/// <param name="key">The key of the element to remove.</param>
|
|||
/// <returns>
|
|||
/// true if the element is successfully removed; otherwise, false. This method also returns false if <paramref name="key"/> was not found in the original <see cref="T:System.Collections.Generic.IDictionary`2"/>.
|
|||
/// </returns>
|
|||
/// <exception cref="T:System.ArgumentNullException">
|
|||
/// <paramref name="key"/> is null.
|
|||
/// </exception>
|
|||
/// <exception cref="T:System.NotSupportedException">
|
|||
/// The <see cref="T:System.Collections.Generic.IDictionary`2"/> is read-only.
|
|||
/// </exception>
|
|||
public bool Remove(TKey key) |
|||
{ |
|||
return Remove(new KeyValuePair<TKey, TValue>(key, default(TValue))); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Adds an element with the provided key and value to the <see cref="T:System.Collections.Generic.IDictionary`2"/>.
|
|||
/// </summary>
|
|||
/// <param name="key">The object to use as the key of the element to add.</param>
|
|||
/// <param name="value">The object to use as the value of the element to add.</param>
|
|||
/// <exception cref="T:System.ArgumentNullException">
|
|||
/// <paramref name="key"/> is null.
|
|||
/// </exception>
|
|||
/// <exception cref="T:System.ArgumentException">
|
|||
/// An element with the same key already exists in the <see cref="T:System.Collections.Generic.IDictionary`2"/>.
|
|||
/// </exception>
|
|||
/// <exception cref="T:System.NotSupportedException">
|
|||
/// The <see cref="T:System.Collections.Generic.IDictionary`2"/> is read-only.
|
|||
/// </exception>
|
|||
public void Add(TKey key, TValue value) |
|||
{ |
|||
if (Equals(key, null)) |
|||
{ |
|||
throw new ArgumentNullException("key"); |
|||
} |
|||
|
|||
Add(new KeyValuePair<TKey, TValue>(key, value)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Determines whether the <see cref="T:System.Collections.Generic.IDictionary`2"/> contains an element with the specified key.
|
|||
/// </summary>
|
|||
/// <param name="key">The key to locate in the <see cref="T:System.Collections.Generic.IDictionary`2"/>.</param>
|
|||
/// <returns>
|
|||
/// true if the <see cref="T:System.Collections.Generic.IDictionary`2"/> contains an element with the key; otherwise, false.
|
|||
/// </returns>
|
|||
/// <exception cref="T:System.ArgumentNullException">
|
|||
/// <paramref name="key"/> is null.
|
|||
/// </exception>
|
|||
public bool ContainsKey(TKey key) |
|||
{ |
|||
return Contains(new KeyValuePair<TKey, TValue>(key, default(TValue)), false); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets an <see cref="T:System.Collections.Generic.ICollection`1"/> containing the keys of the <see cref="T:System.Collections.Generic.IDictionary`2"/>.
|
|||
/// </summary>
|
|||
/// <value></value>
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Trees\BinarySearchTreeBaseExamples.cs" region="Keys" lang="cs" title="The following example shows how to use the Keys property."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Trees\BinarySearchTreeBaseExamples.vb" region="Keys" lang="vbnet" title="The following example shows how to use the Keys property."/>
|
|||
/// </example>
|
|||
public ICollection<TKey> Keys |
|||
{ |
|||
get |
|||
{ |
|||
// Get the keys in sorted order
|
|||
var visitor = new KeyTrackingVisitor<TKey, TValue>(); |
|||
var inOrderVisitor = new InOrderVisitor<KeyValuePair<TKey, TValue>>(visitor); |
|||
DepthFirstTraversal(inOrderVisitor); |
|||
return new ReadOnlyCollection<TKey>(visitor.TrackingList); |
|||
} |
|||
} |
|||
|
|||
|
|||
/// <inheritdoc />
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Trees\BinarySearchTreeBaseExamples.cs" region="TryGetValue" lang="cs" title="The following example shows how to use the TryGetValue method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Trees\BinarySearchTreeBaseExamples.vb" region="TryGetValue" lang="vbnet" title="The following example shows how to use the TryGetValue method."/>
|
|||
/// </example>
|
|||
public bool TryGetValue(TKey key, out TValue value) |
|||
{ |
|||
var node = FindNode(new KeyValuePair<TKey, TValue>(key, default(TValue))); |
|||
|
|||
if (node == null) |
|||
{ |
|||
value = default(TValue); |
|||
return false; |
|||
} |
|||
|
|||
value = node.Data.Value; |
|||
return true; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets an <see cref="T:System.Collections.Generic.ICollection`1"/> containing the values in the <see cref="T:System.Collections.Generic.IDictionary`2"/>.
|
|||
/// </summary>
|
|||
/// <value></value>
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Trees\BinarySearchTreeBaseExamples.cs" region="Values" lang="cs" title="The following example shows how to use the Values property."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Trees\BinarySearchTreeBaseExamples.vb" region="Values" lang="vbnet" title="The following example shows how to use the Values property."/>
|
|||
/// </example>
|
|||
public ICollection<TValue> Values |
|||
{ |
|||
get |
|||
{ |
|||
var visitor = new ValueTrackingVisitor<TKey, TValue>(); |
|||
var inOrderVisitor = new InOrderVisitor<KeyValuePair<TKey, TValue>>(visitor); |
|||
|
|||
DepthFirstTraversal(inOrderVisitor); |
|||
|
|||
return new ReadOnlyCollection<TValue>(visitor.TrackingList); |
|||
} |
|||
} |
|||
|
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the value with the specified key.
|
|||
/// </summary>
|
|||
/// <value>The key of the item to set or get.</value>
|
|||
public TValue this[TKey key] |
|||
{ |
|||
get |
|||
{ |
|||
var node = FindNode(key); |
|||
|
|||
if (node == null) |
|||
{ |
|||
throw new KeyNotFoundException("key"); |
|||
} |
|||
|
|||
return node.Data.Value; |
|||
} |
|||
set |
|||
{ |
|||
var node = FindNode(key); |
|||
|
|||
if (node == null) |
|||
{ |
|||
throw new KeyNotFoundException("key"); |
|||
} |
|||
|
|||
node.Data = new KeyValuePair<TKey, TValue>(key, value); |
|||
} |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region ICollection<KeyValuePair<TKey,TValue>> Members
|
|||
|
|||
/// <inheritdoc />
|
|||
/// <example>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryCSharp\DataStructures\Trees\BinarySearchTreeBaseExamples.cs" region="Contains" lang="cs" title="The following example shows how to use the Contains method."/>
|
|||
/// <code source="..\..\Source\Examples\ExampleLibraryVB\DataStructures\Trees\BinarySearchTreeBaseExamples.vb" region="Contains" lang="vbnet" title="The following example shows how to use the Contains method."/>
|
|||
/// </example>
|
|||
public override bool Contains(KeyValuePair<TKey, TValue> item) |
|||
{ |
|||
return Contains(item, true); |
|||
} |
|||
|
|||
#endregion
|
|||
} |
|||
} |
|||
@ -1,232 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
/* |
|||
Copyright 2007-2013 The NGenerics Team |
|||
(https://github.com/ngenerics/ngenerics/wiki/Team)
|
|||
|
|||
This program is licensed under the GNU Lesser General Public License (LGPL). You should |
|||
have received a copy of the license along with the source code. If not, an online copy |
|||
of the license can be found at http://www.gnu.org/copyleft/lesser.html.
|
|||
*/ |
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Diagnostics; |
|||
using System.Diagnostics.CodeAnalysis; |
|||
|
|||
namespace NGenerics.DataStructures.Trees |
|||
{ |
|||
/// <summary>
|
|||
/// A RedBlack Tree list variant. Equivalent to <see cref="RedBlackTree{TKey,TValue}"/> where TValue is a <see cref="LinkedList{T}"/>.
|
|||
/// </summary>
|
|||
/// <typeparam name="TKey">The type of the key.</typeparam>
|
|||
/// <typeparam name="TValue">The type of the value.</typeparam>
|
|||
//[Serializable]
|
|||
internal class RedBlackTreeList<TKey, TValue> : RedBlackTree<TKey, LinkedList<TValue>> |
|||
{ |
|||
#region Delegates
|
|||
|
|||
private delegate bool NodeAction(TKey key, LinkedList<TValue> values); |
|||
|
|||
#endregion
|
|||
|
|||
#region Construction
|
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="RedBlackTreeList<TKey, TValue>"/> class.
|
|||
/// </summary>
|
|||
/// <inheritdoc/>
|
|||
public RedBlackTreeList() |
|||
{ |
|||
// Do nothing else.
|
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public RedBlackTreeList(IComparer<TKey> comparer) |
|||
: base(comparer) |
|||
{ |
|||
// Do nothing else.
|
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public RedBlackTreeList(Comparison<TKey> comparison) |
|||
: base(comparison) |
|||
{ |
|||
// Do nothing else.
|
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region Public Members
|
|||
|
|||
/// <summary>
|
|||
/// Determines whether the specified value contains value.
|
|||
/// </summary>
|
|||
/// <param name="value">The value.</param>
|
|||
/// <returns>
|
|||
/// <c>true</c> if the specified value contains value; otherwise, <c>false</c>.
|
|||
/// </returns>
|
|||
public bool ContainsValue(TValue value) |
|||
{ |
|||
return TraverseItems((key, list) => list.Contains(value)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the value enumerator.
|
|||
/// </summary>
|
|||
/// <returns>An enumerator to enumerate through the values contained in this instance.</returns>
|
|||
public IEnumerator<TValue> GetValueEnumerator() |
|||
{ |
|||
var stack = new Stack<BinaryTree<KeyValuePair<TKey, LinkedList<TValue>>>>(); |
|||
|
|||
if (Tree != null) |
|||
{ |
|||
stack.Push(Tree); |
|||
} |
|||
|
|||
while (stack.Count > 0) |
|||
{ |
|||
var currentNode = stack.Pop(); |
|||
|
|||
var list = currentNode.Data.Value; |
|||
|
|||
foreach (var item in list) |
|||
{ |
|||
yield return item; |
|||
} |
|||
|
|||
if (currentNode.Left != null) |
|||
{ |
|||
stack.Push(currentNode.Left); |
|||
} |
|||
|
|||
if (currentNode.Right != null) |
|||
{ |
|||
stack.Push(currentNode.Right); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns an enumerator that iterates through the collection.
|
|||
/// </summary>
|
|||
/// <returns>
|
|||
/// A <see cref="IEnumerator{T}"/> that can be used to iterate through the collection.
|
|||
/// </returns>
|
|||
[SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures")] |
|||
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")] |
|||
public IEnumerator<KeyValuePair<TKey, TValue>> GetKeyEnumerator() |
|||
{ |
|||
var stack = new Stack<BinaryTree<KeyValuePair<TKey, LinkedList<TValue>>>>(); |
|||
|
|||
if (Tree != null) |
|||
{ |
|||
stack.Push(Tree); |
|||
} |
|||
|
|||
while (stack.Count > 0) |
|||
{ |
|||
var currentNode = stack.Pop(); |
|||
|
|||
var list = currentNode.Data.Value; |
|||
|
|||
foreach (var item in list) |
|||
{ |
|||
yield return new KeyValuePair<TKey, TValue>(currentNode.Data.Key, item); |
|||
} |
|||
|
|||
if (currentNode.Left != null) |
|||
{ |
|||
stack.Push(currentNode.Left); |
|||
} |
|||
|
|||
if (currentNode.Right != null) |
|||
{ |
|||
stack.Push(currentNode.Right); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Removes the specified value.
|
|||
/// </summary>
|
|||
/// <param name="value">The value.</param>
|
|||
/// <param name="key">The key under which the item was found.</param>
|
|||
/// <returns>A value indicating whether the item was found or not.</returns>
|
|||
public bool Remove(TValue value, out TKey key) |
|||
{ |
|||
var foundKey = default(TKey); |
|||
|
|||
var ret = TraverseItems( |
|||
delegate (TKey itemKey, LinkedList<TValue> list) |
|||
{ |
|||
if (list.Remove(value)) |
|||
{ |
|||
if (list.Count == 0) |
|||
{ |
|||
Remove(itemKey); |
|||
} |
|||
|
|||
foundKey = itemKey; |
|||
return true; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
); |
|||
|
|||
key = foundKey; |
|||
return ret; |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region Private Members
|
|||
|
|||
/// <summary>
|
|||
/// Traverses the items.
|
|||
/// </summary>
|
|||
/// <param name="shouldStop">A predicate that performs an action on the list, and indicates whether the enumeration of items should stop or not.</param>
|
|||
/// <returns>An indication of whether the enumeration was stopped prematurely.</returns>
|
|||
private bool TraverseItems(NodeAction shouldStop) |
|||
{ |
|||
#region Validation
|
|||
|
|||
Debug.Assert(shouldStop != null); |
|||
|
|||
#endregion
|
|||
|
|||
var stack = new Stack<BinaryTree<KeyValuePair<TKey, LinkedList<TValue>>>>(); |
|||
|
|||
if (Tree != null) |
|||
{ |
|||
stack.Push(Tree); |
|||
} |
|||
|
|||
while (stack.Count > 0) |
|||
{ |
|||
var currentNode = stack.Pop(); |
|||
|
|||
if (shouldStop(currentNode.Data.Key, currentNode.Data.Value)) |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
if (currentNode.Left != null) |
|||
{ |
|||
stack.Push(currentNode.Left); |
|||
} |
|||
|
|||
if (currentNode.Right != null) |
|||
{ |
|||
stack.Push(currentNode.Right); |
|||
} |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
#endregion
|
|||
} |
|||
} |
|||
@ -1,107 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
/* |
|||
Copyright 2007-2013 The NGenerics Team |
|||
(https://github.com/ngenerics/ngenerics/wiki/Team)
|
|||
|
|||
This program is licensed under the GNU Lesser General Public License (LGPL). You should |
|||
have received a copy of the license along with the source code. If not, an online copy |
|||
of the license can be found at http://www.gnu.org/copyleft/lesser.html.
|
|||
*/ |
|||
|
|||
|
|||
|
|||
using System; |
|||
using System.Diagnostics.CodeAnalysis; |
|||
|
|||
namespace NGenerics.DataStructures.Trees |
|||
{ |
|||
/// <summary>
|
|||
/// A container class, used for the RedBlackTree.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The type of element.</typeparam>
|
|||
//[Serializable]
|
|||
[SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix")] |
|||
internal class RedBlackTreeNode<T> : BinaryTree<T> |
|||
{ |
|||
#region Construction
|
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="RedBlackTreeNode<T>"/> class.
|
|||
/// </summary>
|
|||
/// <param name="data">The data contained in this node.</param>
|
|||
internal RedBlackTreeNode(T data) |
|||
: base(data) |
|||
{ |
|||
Color = NodeColor.Red; |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region Properties
|
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the color of the current node.
|
|||
/// </summary>
|
|||
/// <value>The color of the node.</value>
|
|||
internal NodeColor Color { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the <see cref="NGenerics.DataStructures.Trees.BinaryTree<T>"/> with the specified direction.
|
|||
/// </summary>
|
|||
/// <value></value>
|
|||
internal RedBlackTreeNode<T> this[bool direction] |
|||
{ |
|||
get |
|||
{ |
|||
return direction ? Right : Left; |
|||
} |
|||
set |
|||
{ |
|||
if (direction) |
|||
{ |
|||
Right = value; |
|||
} |
|||
else |
|||
{ |
|||
Left = value; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the left subtree.
|
|||
/// </summary>
|
|||
/// <value>The left subtree.</value>
|
|||
internal new RedBlackTreeNode<T> Left |
|||
{ |
|||
get |
|||
{ |
|||
return (RedBlackTreeNode<T>)base.Left; |
|||
} |
|||
set |
|||
{ |
|||
base.Left = value; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the right subtree.
|
|||
/// </summary>
|
|||
/// <value>The right subtree.</value>
|
|||
internal new RedBlackTreeNode<T> Right |
|||
{ |
|||
get |
|||
{ |
|||
return (RedBlackTreeNode<T>)base.Right; |
|||
} |
|||
set |
|||
{ |
|||
base.Right = value; |
|||
} |
|||
} |
|||
|
|||
#endregion
|
|||
} |
|||
} |
|||
@ -1,76 +0,0 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> |
|||
<PropertyGroup> |
|||
<MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion> |
|||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> |
|||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> |
|||
<ProjectGuid>{415E048E-4611-4815-9CF2-D774E29079AC}</ProjectGuid> |
|||
<OutputType>Library</OutputType> |
|||
<AppDesignerFolder>Properties</AppDesignerFolder> |
|||
<RootNamespace>NGenerics</RootNamespace> |
|||
<AssemblyName>NGenerics</AssemblyName> |
|||
<DefaultLanguage>en-US</DefaultLanguage> |
|||
<FileAlignment>512</FileAlignment> |
|||
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> |
|||
<TargetFrameworkProfile>Profile7</TargetFrameworkProfile> |
|||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
|||
<DebugSymbols>true</DebugSymbols> |
|||
<DebugType>full</DebugType> |
|||
<Optimize>false</Optimize> |
|||
<OutputPath>bin\Debug\</OutputPath> |
|||
<DefineConstants>DEBUG;TRACE</DefineConstants> |
|||
<ErrorReport>prompt</ErrorReport> |
|||
<WarningLevel>4</WarningLevel> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> |
|||
<DebugType>pdbonly</DebugType> |
|||
<Optimize>true</Optimize> |
|||
<OutputPath>bin\Release\</OutputPath> |
|||
<DefineConstants>TRACE</DefineConstants> |
|||
<ErrorReport>prompt</ErrorReport> |
|||
<WarningLevel>4</WarningLevel> |
|||
</PropertyGroup> |
|||
<ItemGroup> |
|||
<!-- A reference to the entire .NET Framework is automatically included --> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<Compile Include="DataStructures\Comparers\ReverseComparer.cs" /> |
|||
<Compile Include="DataStructures\General\Heap.cs" /> |
|||
<Compile Include="DataStructures\General\HeapType.cs" /> |
|||
<Compile Include="DataStructures\General\IHeap.cs" /> |
|||
<Compile Include="DataStructures\Trees\BinarySearchTreeBase.cs" /> |
|||
<Compile Include="DataStructures\Trees\BinaryTree.cs" /> |
|||
<Compile Include="DataStructures\Comparers\ComparisonComparer.cs" /> |
|||
<Compile Include="Constants.cs" /> |
|||
<Compile Include="Util\Guard.cs" /> |
|||
<Compile Include="Patterns\Visitor\InOrderVisitor.cs" /> |
|||
<Compile Include="DataStructures\Queues\IQueue.cs" /> |
|||
<Compile Include="DataStructures\Trees\ISearchTree.cs" /> |
|||
<Compile Include="DataStructures\Trees\ITree.cs" /> |
|||
<Compile Include="Patterns\Visitor\IVisitor.cs" /> |
|||
<Compile Include="Patterns\Visitor\KeyTrackingVisitor.cs" /> |
|||
<Compile Include="DataStructures\Comparers\KeyValuePairComparer.cs" /> |
|||
<Compile Include="DataStructures\Trees\NodeColor.cs" /> |
|||
<Compile Include="Patterns\Visitor\OrderedVisitor.cs" /> |
|||
<Compile Include="DataStructures\Queues\PriorityQueue.cs" /> |
|||
<Compile Include="DataStructures\Queues\PriorityQueueType.cs" /> |
|||
<Compile Include="Properties\AssemblyInfo.cs" /> |
|||
<Compile Include="DataStructures\Trees\RedBlackTree.cs" /> |
|||
<Compile Include="DataStructures\Trees\RedBlackTreeDictionary.cs" /> |
|||
<Compile Include="DataStructures\Trees\RedBlackTreeList.cs" /> |
|||
<Compile Include="DataStructures\Trees\RedBlackTreeNode.cs" /> |
|||
<Compile Include="Patterns\Visitor\TrackingVisitor.cs" /> |
|||
<Compile Include="Patterns\Visitor\ValueTrackingVisitor.cs" /> |
|||
</ItemGroup> |
|||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" /> |
|||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. |
|||
Other similar extension points exist, see Microsoft.Common.targets. |
|||
<Target Name="BeforeBuild"> |
|||
</Target> |
|||
<Target Name="AfterBuild"> |
|||
</Target> |
|||
--> |
|||
</Project> |
|||
@ -1,34 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
/* |
|||
Copyright 2007-2013 The NGenerics Team |
|||
(https://github.com/ngenerics/ngenerics/wiki/Team)
|
|||
|
|||
This program is licensed under the GNU Lesser General Public License (LGPL). You should |
|||
have received a copy of the license along with the source code. If not, an online copy |
|||
of the license can be found at http://www.gnu.org/copyleft/lesser.html.
|
|||
*/ |
|||
|
|||
|
|||
namespace NGenerics.Patterns.Visitor |
|||
{ |
|||
/// <summary>
|
|||
/// Provides an interface for visitors.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The type of objects to be visited.</typeparam>
|
|||
public interface IVisitor<T> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets a value indicating whether this instance is done performing it's work..
|
|||
/// </summary>
|
|||
/// <value><c>true</c> if this instance is done; otherwise, <c>false</c>.</value>
|
|||
bool HasCompleted { get; } |
|||
|
|||
/// <summary>
|
|||
/// Visits the specified object.
|
|||
/// </summary>
|
|||
/// <param name="obj">The object to visit.</param>
|
|||
void Visit(T obj); |
|||
} |
|||
} |
|||
@ -1,51 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
/* |
|||
Copyright 2007-2013 The NGenerics Team |
|||
(https://github.com/ngenerics/ngenerics/wiki/Team)
|
|||
|
|||
This program is licensed under the GNU Lesser General Public License (LGPL). You should |
|||
have received a copy of the license along with the source code. If not, an online copy |
|||
of the license can be found at http://www.gnu.org/copyleft/lesser.html.
|
|||
*/ |
|||
|
|||
|
|||
namespace NGenerics.Patterns.Visitor |
|||
{ |
|||
/// <summary>
|
|||
/// An in order implementation of the <see cref="OrderedVisitor{T}"/> class.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The type of objects to be visited.</typeparam>
|
|||
public sealed class InOrderVisitor<T> : OrderedVisitor<T> |
|||
{ |
|||
#region Construction
|
|||
|
|||
/// <param name="visitor">The visitor.</param>
|
|||
public InOrderVisitor(IVisitor<T> visitor) : base(visitor) { } |
|||
|
|||
#endregion
|
|||
|
|||
#region OrderedVisitor<T> Members
|
|||
|
|||
/// <summary>
|
|||
/// Visits the object in post order.
|
|||
/// </summary>
|
|||
/// <param name="obj">The obj.</param>
|
|||
public override void VisitPostOrder(T obj) |
|||
{ |
|||
// Do nothing.
|
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Visits the object in pre order.
|
|||
/// </summary>
|
|||
/// <param name="obj">The obj.</param>
|
|||
public override void VisitPreOrder(T obj) |
|||
{ |
|||
// Do nothing.
|
|||
} |
|||
|
|||
#endregion
|
|||
} |
|||
} |
|||
@ -1,65 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
/* |
|||
Copyright 2007-2013 The NGenerics Team |
|||
(https://github.com/ngenerics/ngenerics/wiki/Team)
|
|||
|
|||
This program is licensed under the GNU Lesser General Public License (LGPL). You should |
|||
have received a copy of the license along with the source code. If not, an online copy |
|||
of the license can be found at http://www.gnu.org/copyleft/lesser.html.
|
|||
*/ |
|||
|
|||
|
|||
using System.Collections.Generic; |
|||
|
|||
namespace NGenerics.Patterns.Visitor |
|||
{ |
|||
/// <summary>
|
|||
/// A visitor that tracks (stores) keys from KeyValuePAirs in the order they were visited.
|
|||
/// </summary>
|
|||
/// <typeparam name="TKey">The type of the keys for the items to be visited.</typeparam>
|
|||
/// <typeparam name="TValue">The type of the values for the items to be visited.</typeparam>
|
|||
public sealed class KeyTrackingVisitor<TKey, TValue> : IVisitor<KeyValuePair<TKey, TValue>> |
|||
{ |
|||
#region Globals
|
|||
|
|||
private readonly List<TKey> _tracks; |
|||
|
|||
#endregion
|
|||
|
|||
#region Construction
|
|||
|
|||
/// <inheritdoc/>
|
|||
public KeyTrackingVisitor() |
|||
{ |
|||
_tracks = new List<TKey>(); |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region Public Members
|
|||
|
|||
/// <summary>
|
|||
/// Gets the tracking list.
|
|||
/// </summary>
|
|||
/// <value>The tracking list.</value>
|
|||
public IList<TKey> TrackingList => _tracks; |
|||
|
|||
#endregion
|
|||
|
|||
#region IVisitor<KeyValuePair<TKey,TValue>> Members
|
|||
|
|||
|
|||
/// <inheritdoc />
|
|||
public void Visit(KeyValuePair<TKey, TValue> obj) |
|||
{ |
|||
_tracks.Add(obj.Key); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public bool HasCompleted => false; |
|||
|
|||
#endregion
|
|||
} |
|||
} |
|||
@ -1,102 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
/* |
|||
Copyright 2007-2013 The NGenerics Team |
|||
(https://github.com/ngenerics/ngenerics/wiki/Team)
|
|||
|
|||
This program is licensed under the GNU Lesser General Public License (LGPL). You should |
|||
have received a copy of the license along with the source code. If not, an online copy |
|||
of the license can be found at http://www.gnu.org/copyleft/lesser.html.
|
|||
*/ |
|||
|
|||
|
|||
using System; |
|||
using System.Diagnostics.CodeAnalysis; |
|||
using NGenerics.Util; |
|||
|
|||
namespace NGenerics.Patterns.Visitor |
|||
{ |
|||
/// <summary>
|
|||
/// A visitor that visits objects in order (PreOrder, PostOrder, or InOrder).
|
|||
/// Used primarily as a base class for Visitors specializing in a specific order type.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The type of objects to be visited.</typeparam>
|
|||
public class OrderedVisitor<T> : IVisitor<T> |
|||
{ |
|||
#region Globals
|
|||
|
|||
private readonly IVisitor<T> _visitorToUse; |
|||
|
|||
#endregion
|
|||
|
|||
#region Construction
|
|||
|
|||
/// <param name="visitorToUse">The visitor to use when visiting the object.</param>
|
|||
/// <exception cref="ArgumentNullException"><paramref name="visitorToUse"/> is a null reference (<c>Nothing</c> in Visual Basic).</exception>
|
|||
public OrderedVisitor(IVisitor<T> visitorToUse) |
|||
{ |
|||
Guard.ArgumentNotNull(visitorToUse, "visitorToUse"); |
|||
|
|||
_visitorToUse = visitorToUse; |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region IOrderedVisitor<T> Members
|
|||
|
|||
/// <summary>
|
|||
/// Determines whether this visitor is done.
|
|||
/// </summary>
|
|||
/// <value></value>
|
|||
/// <returns>
|
|||
/// <c>true</c> if this visitor is done; otherwise, <c>false</c>.
|
|||
/// </returns>
|
|||
public bool HasCompleted => _visitorToUse.HasCompleted; |
|||
|
|||
/// <summary>
|
|||
/// Visits the object in pre order.
|
|||
/// </summary>
|
|||
/// <param name="obj">The obj.</param>
|
|||
[SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "PreOrder")] |
|||
public virtual void VisitPreOrder(T obj) |
|||
{ |
|||
_visitorToUse.Visit(obj); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Visits the object in post order.
|
|||
/// </summary>
|
|||
/// <param name="obj">The obj.</param>
|
|||
public virtual void VisitPostOrder(T obj) |
|||
{ |
|||
_visitorToUse.Visit(obj); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Visits the object in order.
|
|||
/// </summary>
|
|||
/// <param name="obj">The obj.</param>
|
|||
public virtual void VisitInOrder(T obj) |
|||
{ |
|||
_visitorToUse.Visit(obj); |
|||
} |
|||
/// <inheritdoc />
|
|||
public void Visit(T obj) |
|||
{ |
|||
_visitorToUse.Visit(obj); |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region Public Members
|
|||
|
|||
/// <summary>
|
|||
/// Gets the visitor to use.
|
|||
/// </summary>
|
|||
/// <value>The visitor to use.</value>
|
|||
public IVisitor<T> VisitorToUse => _visitorToUse; |
|||
|
|||
#endregion
|
|||
} |
|||
} |
|||
@ -1,65 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
/* |
|||
Copyright 2007-2013 The NGenerics Team |
|||
(https://github.com/ngenerics/ngenerics/wiki/Team)
|
|||
|
|||
This program is licensed under the GNU Lesser General Public License (LGPL). You should |
|||
have received a copy of the license along with the source code. If not, an online copy |
|||
of the license can be found at http://www.gnu.org/copyleft/lesser.html.
|
|||
*/ |
|||
|
|||
|
|||
using System.Collections.Generic; |
|||
|
|||
namespace NGenerics.Patterns.Visitor |
|||
{ |
|||
/// <summary>
|
|||
/// A visitor that tracks (stores) objects in the order they were visited.
|
|||
/// Handy for demonstrating and testing different ordered visits implementations on
|
|||
/// data structures.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The type of objects to be visited.</typeparam>
|
|||
public sealed class TrackingVisitor<T> : IVisitor<T> |
|||
{ |
|||
#region Globals
|
|||
|
|||
private readonly List<T> _tracks; |
|||
|
|||
#endregion
|
|||
|
|||
#region Construction
|
|||
|
|||
|
|||
/// <inheritdoc/>
|
|||
public TrackingVisitor() |
|||
{ |
|||
_tracks = new List<T>(); |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region IVisitor<T> Members
|
|||
/// <inheritdoc />
|
|||
public void Visit(T obj) |
|||
{ |
|||
_tracks.Add(obj); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public bool HasCompleted => false; |
|||
|
|||
#endregion
|
|||
|
|||
#region Public Members
|
|||
|
|||
/// <summary>
|
|||
/// Gets the tracking list.
|
|||
/// </summary>
|
|||
/// <value>The tracking list.</value>
|
|||
public IList<T> TrackingList => _tracks; |
|||
|
|||
#endregion
|
|||
} |
|||
} |
|||
@ -1,66 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
/* |
|||
Copyright 2007-2013 The NGenerics Team |
|||
(https://github.com/ngenerics/ngenerics/wiki/Team)
|
|||
|
|||
This program is licensed under the GNU Lesser General Public License (LGPL). You should |
|||
have received a copy of the license along with the source code. If not, an online copy |
|||
of the license can be found at http://www.gnu.org/copyleft/lesser.html.
|
|||
*/ |
|||
|
|||
|
|||
using System.Collections.Generic; |
|||
|
|||
namespace NGenerics.Patterns.Visitor |
|||
{ |
|||
/// <summary>
|
|||
/// A visitor that tracks (stores) keys from KeyValuePairs in the order they were visited.
|
|||
/// </summary>
|
|||
/// <typeparam name="TKey">The type of key of the KeyValuePair.</typeparam>
|
|||
/// <typeparam name="TValue">The type of value of the KeyValuePair.</typeparam>
|
|||
public sealed class ValueTrackingVisitor<TKey, TValue> : IVisitor<KeyValuePair<TKey, TValue>> |
|||
{ |
|||
#region Globals
|
|||
|
|||
private readonly List<TValue> _tracks; |
|||
|
|||
#endregion
|
|||
|
|||
#region Construction
|
|||
|
|||
|
|||
/// <inheritdoc/>
|
|||
public ValueTrackingVisitor() |
|||
{ |
|||
_tracks = new List<TValue>(); |
|||
} |
|||
|
|||
#endregion
|
|||
|
|||
#region Public Members
|
|||
|
|||
/// <summary>
|
|||
/// Gets the tracking list.
|
|||
/// </summary>
|
|||
/// <value>The tracking list.</value>
|
|||
public IList<TValue> TrackingList => _tracks; |
|||
|
|||
#endregion
|
|||
|
|||
#region IVisitor<KeyValuePair<TKey,TValue>> Members
|
|||
|
|||
|
|||
/// <inheritdoc />
|
|||
public void Visit(KeyValuePair<TKey, TValue> obj) |
|||
{ |
|||
_tracks.Add(obj.Value); |
|||
} |
|||
|
|||
/// <inheritdoc />
|
|||
public bool HasCompleted => false; |
|||
|
|||
#endregion
|
|||
} |
|||
} |
|||
@ -1,33 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
using System.Resources; |
|||
using System.Reflection; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
// General Information about an assembly is controlled through the following
|
|||
// set of attributes. Change these attribute values to modify the information
|
|||
// associated with an assembly.
|
|||
[assembly: AssemblyTitle("NGenerics")] |
|||
[assembly: AssemblyDescription("")] |
|||
[assembly: AssemblyConfiguration("")] |
|||
[assembly: AssemblyCompany("")] |
|||
[assembly: AssemblyProduct("NGenerics")] |
|||
[assembly: AssemblyCopyright("Copyright \u00A9 2014")] |
|||
[assembly: AssemblyTrademark("")] |
|||
[assembly: AssemblyCulture("")] |
|||
[assembly: NeutralResourcesLanguage("en")] |
|||
|
|||
// Version information for an assembly consists of the following four values:
|
|||
//
|
|||
// Major Version
|
|||
// Minor Version
|
|||
// Build Number
|
|||
// Revision
|
|||
//
|
|||
// You can specify all the values or you can default the Build and Revision Numbers
|
|||
// by using the '*' as shown below:
|
|||
// [assembly: AssemblyVersion("1.0.*")]
|
|||
[assembly: AssemblyVersion("1.0.0.0")] |
|||
[assembly: AssemblyFileVersion("1.0.0.0")] |
|||
@ -1,59 +0,0 @@ |
|||
// Copyright (c) The Perspex Project. All rights reserved.
|
|||
// Licensed under the MIT license. See licence.md file in the project root for full license information.
|
|||
|
|||
/* |
|||
Copyright 2007-2013 The NGenerics Team |
|||
(https://github.com/ngenerics/ngenerics/wiki/Team)
|
|||
|
|||
This program is licensed under the GNU Lesser General Public License (LGPL). You should |
|||
have received a copy of the license along with the source code. If not, an online copy |
|||
of the license can be found at http://www.gnu.org/copyleft/lesser.html.
|
|||
*/ |
|||
|
|||
|
|||
using System; |
|||
|
|||
namespace NGenerics.Util |
|||
{ |
|||
/// <summary>
|
|||
/// Performs common argument validation.
|
|||
/// </summary>
|
|||
public static class Guard |
|||
{ |
|||
#region Methods
|
|||
|
|||
/// <summary>
|
|||
/// Checks a string argument to ensure it isn't null or empty.
|
|||
/// </summary>
|
|||
/// <param name="argumentValue">The argument value to check.</param>
|
|||
/// <param name="argumentName">The name of the argument.</param>
|
|||
/// <exception cref="ArgumentNullException"><paramref name="argumentValue"/> is a null reference.</exception>
|
|||
/// <exception cref="ArgumentException"><paramref name="argumentValue"/> is <see cref="string.Empty"/>.</exception>
|
|||
public static void ArgumentNotNullOrEmptyString(string argumentValue, string argumentName) |
|||
{ |
|||
ArgumentNotNull(argumentValue, argumentName); |
|||
|
|||
if (argumentValue.Length == 0) |
|||
{ |
|||
throw new ArgumentException("String cannot be empty.", argumentName); |
|||
} |
|||
} |
|||
|
|||
|
|||
/// <summary>
|
|||
/// Checks an argument to ensure it isn't null.
|
|||
/// </summary>
|
|||
/// <param name="argumentValue">The argument value to check.</param>
|
|||
/// <param name="argumentName">The name of the argument.</param>
|
|||
/// <exception cref="ArgumentNullException"><paramref name="argumentValue"/> is a null reference.</exception>
|
|||
public static void ArgumentNotNull(object argumentValue, string argumentName) |
|||
{ |
|||
if (argumentValue == null) |
|||
{ |
|||
throw new ArgumentNullException(argumentName); |
|||
} |
|||
} |
|||
|
|||
#endregion
|
|||
} |
|||
} |
|||
Loading…
Reference in new issue