.NET框架具有的Array.Sort过载,允许一个指定的起始和结束indicies用于排序要遵循。然而,这些参数仅仅是32比特。所以,我不明白的方式时,只能用一个64位的号码来确定描述的排序范围的indicies排序大阵的一部分。我想我可以复制和修改框架的排序实现,但效果不理想。

更新

我已经创建了两个类来帮助我身边的这些和其他大型阵列的问题。其他的其中一个问题是,很久以前我得到了我的内存限制,我开始越来越OutOfMemoryException异常的。我假设这是因为请求的内存可能存在,但不是连续的。因此,对于这一点,我创建的类BigArray,这是阵列的一个通用的,可动态调整大小列表。它有一个更小的内存占用比框架的泛型列表类,并且不要求整个阵列是连续的。我没有测试过性能损失,但我敢肯定它的存在。

  public class BigArray<T> : IEnumerable<T>
  {
    private long capacity;
    private int itemsPerBlock;
    private int shift;
    private List<T[]> blocks = new List<T[]>();

    public BigArray(int itemsPerBlock)
    {
      shift = (int)Math.Ceiling(Math.Log(itemsPerBlock) / Math.Log(2));
      this.itemsPerBlock = 1 << shift;
    }

    public long Capacity
    {
      get
      {
        return capacity;
      }
      set
      {
        var requiredBlockCount = (value - 1) / itemsPerBlock + 1;
        while (blocks.Count > requiredBlockCount)
        {
          blocks.RemoveAt(blocks.Count - 1);
        }
        while (blocks.Count < requiredBlockCount)
        {
          blocks.Add(new T[itemsPerBlock]);
        }
        capacity = (long)itemsPerBlock * blocks.Count;
      }
    }

    public T this[long index]
    {
      get
      {
        Debug.Assert(index < capacity);
        var blockNumber = (int)(index >> shift);
        var itemNumber = index & (itemsPerBlock - 1);
        return blocks[blockNumber][itemNumber];
      }
      set
      {
        Debug.Assert(index < capacity);
        var blockNumber = (int)(index >> shift);
        var itemNumber = index & (itemsPerBlock - 1);
        blocks[blockNumber][itemNumber] = value;
      }
    }

    public IEnumerator<T> GetEnumerator()
    {
      for (long i = 0; i < capacity; i++)
      {
        yield return this[i];
      }
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
      return this.GetEnumerator();
    }

  }

和又回到了整理的原始问题......我真正需要的是起到一个数组中的每个元素,以一种方式。但是,这样大的阵列,它是高昂的复制数据,排序,作用于它,然后丢弃排序复印件(原来的顺序必须保持)。因此,我创建静态类OrderedOperation,它允许你一个排序的数组中的每个元素上执行任意的操作中,排序顺序。和具有低存储器足迹(这里为执行时间交易存储器)这样做。

  public static class OrderedOperation
  {
    public delegate void WorkerDelegate(int index, float progress);

    public static void Process(WorkerDelegate worker, IEnumerable<int> items, int count, int maxItem, int maxChunkSize)
    {
      // create a histogram such that a single bin is never bigger than a chunk
      int binCount = 1000;
      int[] bins;
      double binScale;
      bool ok;
      do
      {
        ok = true;
        bins = new int[binCount];
        binScale = (double)(binCount - 1) / maxItem;
        int i = 0;
        foreach (int item in items)
        {
          bins[(int)(binScale * item)]++;
          if (++i == count)
          {
            break;
          }
        }
        for (int b = 0; b < binCount; b++)
        {
          if (bins[b] > maxChunkSize)
          {
            ok = false;
            binCount *= 2;
            break;
          }
        }
      } while (!ok);

      var chunkData = new int[maxChunkSize];
      var chunkIndex = new int[maxChunkSize];
      var done = new System.Collections.BitArray(count);
      var processed = 0;
      var binsCompleted = 0;
      while (binsCompleted < binCount)
      {
        var chunkMax = 0;
        var sum = 0;
        do
        {
          sum += bins[binsCompleted];
          binsCompleted++;
        } while (binsCompleted < binCount - 1 && sum + bins[binsCompleted] <= maxChunkSize);
        Debug.Assert(sum <= maxChunkSize);
        chunkMax = (int)Math.Ceiling((double)binsCompleted / binScale);
        var chunkCount = 0;
        int i = 0;
        foreach (int item in items)
        {
          if (item < chunkMax && !done[i])
          {
            chunkData[chunkCount] = item;
            chunkIndex[chunkCount] = i;
            chunkCount++;
            done[i] = true;
          }
          if (++i == count)
          {
            break;
          }
        }
        Debug.Assert(sum == chunkCount);
        Array.Sort(chunkData, chunkIndex, 0, chunkCount);
        for (i = 0; i < chunkCount; i++)
        {
          worker(chunkIndex[i], (float)processed / count);
          processed++;
        }
      }
      Debug.Assert(processed == count);
    }
  }

这两个类可以一起工作(这就是我如何使用它们),但他们没有。我希望别人认为他们是有用的。不过,我得承认,他们是边缘的情况下类。问题欢迎。如果我的代码太烂了,我想听到的提示了。

最后一个想法:正如你可以看到OrderedOperation,我使用的是整数,而不是多头。目前,足以对我来说,尽管原来的问题我有(应用程序是在不断变化,如果你不能告诉)。但类应该能够处理多头为好,如有需要。

有帮助吗?

解决方案

您会发现,即使是在64位的框架,元件的阵列中的最大数量是int.MaxValue

这接受或返回Int64只是铸long值,现有的方法在内部Int32和,在参数的情况下,如果ArgumentOutOfRangeException参数不是longint.MinValue之间将抛出int.MaxValue

例如在LongLength属性,它返回一个Int64,只是投射并返回Length属性的值:

public long LongLength
{
    get { return (long)this.Length; }    // Length is an Int32
}

所以,我的建议是要投你Int64 indicies到Int32,然后调用现有Sort重载之一。

其他提示

由于Array.Copy需要的Int64参数,可以你可以拉出来,你需要排序的部分,排序,然后把它放回去。假设你排序当然小于2 ^ 32个元件。

好像如果要排序超过2 ^ 32元那么这将是最好写你自己的,更有效的,反正排序算法。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top