blob: da0a77896e48ad1b7a45ca5343057b867719ce7c [file] [log] [blame]
using J2N.Collections.Generic.Extensions;
using System;
using System.Collections.Generic;
namespace Lucene.Net.Util
{
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/// <summary>
/// Methods for manipulating (sorting) collections.
/// Sort methods work directly on the supplied lists and don't copy to/from arrays
/// before/after. For medium size collections as used in the Lucene indexer that is
/// much more efficient.
/// <para/>
/// @lucene.internal
/// </summary>
public static class CollectionUtil // LUCENENET specific - made static
{
private sealed class ListIntroSorter<T> : IntroSorter
{
internal T pivot;
internal IList<T> list;
internal readonly IComparer<T> comp;
internal ListIntroSorter(IList<T> list, IComparer<T> comp)
: base()
{
// LUCENENET NOTE: All ILists in .NET are random access (only IEnumerable is forward-only)
//if (!(list is RandomAccess))
//{
// throw new ArgumentException("CollectionUtil can only sort random access lists in-place.");
//}
this.list = list;
this.comp = comp;
}
protected override void SetPivot(int i)
{
pivot = (i < list.Count) ? list[i] : default;
}
protected override void Swap(int i, int j)
{
list.Swap(i, j);
}
protected override int Compare(int i, int j)
{
return comp.Compare(list[i], list[j]);
}
protected override int ComparePivot(int j)
{
return comp.Compare(pivot, list[j]);
}
}
private sealed class ListTimSorter<T> : TimSorter
{
internal IList<T> list;
internal readonly IComparer<T> comp;
internal readonly T[] tmp;
internal ListTimSorter(IList<T> list, IComparer<T> comp, int maxTempSlots)
: base(maxTempSlots)
{
// LUCENENET NOTE: All ILists in .NET are random access (only IEnumerable is forward-only)
//if (!(list is RandomAccess))
//{
// throw new ArgumentException("CollectionUtil can only sort random access lists in-place.");
//}
this.list = list;
this.comp = comp;
if (maxTempSlots > 0)
{
this.tmp = new T[maxTempSlots];
}
else
{
this.tmp = null;
}
}
protected override void Swap(int i, int j)
{
list.Swap(i, j);
}
protected override void Copy(int src, int dest)
{
list[dest] = list[src];
}
protected override void Save(int i, int len)
{
for (int j = 0; j < len; ++j)
{
tmp[j] = list[i + j];
}
}
protected override void Restore(int i, int j)
{
list[j] = tmp[i];
}
protected override int Compare(int i, int j)
{
return comp.Compare(list[i], list[j]);
}
protected override int CompareSaved(int i, int j)
{
return comp.Compare(tmp[i], list[j]);
}
}
/// <summary>
/// Sorts the given <see cref="IList{T}"/> using the <see cref="IComparer{T}"/>.
/// This method uses the intro sort
/// algorithm, but falls back to insertion sort for small lists.
/// </summary>
/// <param name="list">This <see cref="IList{T}"/></param>
/// <param name="comp">The <see cref="IComparer{T}"/> to use for the sort.</param>
public static void IntroSort<T>(IList<T> list, IComparer<T> comp)
{
int size = list.Count;
if (size <= 1)
{
return;
}
(new ListIntroSorter<T>(list, comp)).Sort(0, size);
}
/// <summary>
/// Sorts the given random access <see cref="IList{T}"/> in natural order.
/// This method uses the intro sort
/// algorithm, but falls back to insertion sort for small lists.
/// </summary>
/// <param name="list">This <see cref="IList{T}"/></param>
public static void IntroSort<T>(IList<T> list)
//where T : IComparable<T> // LUCENENET specific: removing constraint because in .NET, it is not needed
{
int size = list.Count;
if (size <= 1)
{
return;
}
IntroSort(list, ArrayUtil.GetNaturalComparer<T>());
}
// Tim sorts:
/// <summary>
/// Sorts the given <see cref="IList{T}"/> using the <see cref="IComparer{T}"/>.
/// This method uses the Tim sort
/// algorithm, but falls back to binary sort for small lists.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="list">this <see cref="IList{T}"/></param>
/// <param name="comp">The <see cref="IComparer{T}"/> to use for the sort.</param>
public static void TimSort<T>(IList<T> list, IComparer<T> comp)
{
int size = list.Count;
if (size <= 1)
{
return;
}
(new ListTimSorter<T>(list, comp, list.Count / 64)).Sort(0, size);
}
/// <summary>
/// Sorts the given <see cref="IList{T}"/> in natural order.
/// This method uses the Tim sort
/// algorithm, but falls back to binary sort for small lists. </summary>
/// <param name="list">This <see cref="IList{T}"/></param>
public static void TimSort<T>(IList<T> list)
//where T : IComparable<T> // LUCENENET specific: removing constraint because in .NET, it is not needed
{
int size = list.Count;
if (size <= 1)
{
return;
}
TimSort(list, ArrayUtil.GetNaturalComparer<T>());
}
}
}