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