【问题标题】:How to shift array elements如何移动数组元素
【发布时间】:2009-04-19 18:36:18
【问题描述】:

我有一个包含 n = 32 个项目的数组,其中包含正值和负值。第一个 n/2 元素是正数并按值排序,第二个 n/2 元素是负数并按值排序。我想按值对整个数组进行排序,从最小的负值到最大的正值,这意味着如果有 32 个元素,则前 16 个(n/2)排序元素应包含原始数组的后 16 个元素的值排序数组的后 16 个元素应包含原始数组的前 16 个值。

假设示例:

double[] original = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, -16, -15, ..., -1};

double[] sorted = {-16, -15, ...., -1, 1, 2, ..., 16};

有谁知道转移元素以从原始生成排序数组的最佳方法是什么?

顺便说一下,这个数组绑定到另一个数组,该数组没有按大小排序的元素,并且必须以与原始相同的方式移动,因此该数组不应该按大小排序,它必须被转移

【问题讨论】:

  • 为什么要移动而不是排序?
  • 因为我必须移动另一个未按大小排序的数组,就像我为这个数组所做的那样。假设的示例表示一个 x 轴,它按大小排序,但另一个数组包含不应按大小(y 轴)排序的值。
  • 您想根据另一个数组中包含的值对一个数组进行排序吗?换句话说:您想对一个数组进行排序,然后将相同的步骤序列应用于另一个数组吗?

标签: .net arrays shift


【解决方案1】:

所以您想要第二个数组,其中包含原始内容但位置已移动?要么明确地做到这一点:

double[] result = new double[32];
for (int i=0; i < 32; i++)
{
    result[(i+16)%32] = original[i];
}

或使用Array.Copy 两次:

double[] result = new double[32];
Array.Copy(original, 0, result, 16, 16);
Array.Copy(original, 16, result, 0, 16);

【讨论】:

    【解决方案2】:

    鉴于问题的刚性,Array.Copy

            int half = original.Length / 2;
            Array.Copy(original, 0, sorted, half, half);
            Array.Copy(original, half, sorted, 0, half);
    

    【讨论】:

      【解决方案3】:

      在 Linq 中怎么样:

      int half = original.Length/2;
      var sorted = original.Skip(half).Concat(original.Take(half)).ToArray();
      

      【讨论】:

      • 我认为您的意思是 Concat 而不是 Union - Union 将删除任何重复的元素。
      • @Jon:谢谢...我做了你建议的改变。
      【解决方案4】:

      你试过了吗:

      Array.Sort(original);
      

      【讨论】:

      • 它必须移动而不是排序!
      • 在您给出的示例中,将使用 Array.Sort 获得所需的结果。
      • 请记住,两半都已排序(根据您的描述)将元素 0 与 16、1 和 17、2 和 19 等移动...将具有与对数组进行排序相同的结果按大小。
      • @Darin Dimitrov - 他无法排序,因为他需要在另一个数组上执行 相同 移位。问题评论中对此进行了解释。
      【解决方案5】:

      只需对元素 0 和元素 16、1 和 17、2 和 18 等进行交换即可。

      【讨论】:

        【解决方案6】:

        您想根据另一个相同大小的数组中包含的值对一个数组进行排序吗?如果是这样,请使用以下内容:

        Array.Sort(keys, values);
        

        这是Array.Sort(Array keys, Array items)的文档

        【讨论】:

          【解决方案7】:

          Jon Skeet 和 Marc Gravell♦ 的回答提供了正确的解决方案,但如果您不想分配额外的数组,您可以:

          a) 解决您的具体问题(将第二半移到第一半之前):

          private void Rotate1(double[] toRotate ) {
                  int startOf2nd = toRotate.Length / 2;
                  for (int i=0; i < toRotate.Length/2; i++) {
                      double temp = toRotate [i];
                      toRotate [i] = toRotate [i + startOf2nd];
                      toRotate [i + startOf2nd] = temp;
                  }
              }
          

          请注意,此代码无法处理包含奇数项的数组。

          b) 您可以应用我从 Jon Bentley 的“Programming Pearls”中了解到的矢量移位算法:

           private void Rotate2(double[] toRotate, int index ) {
                  Array.Reverse(toRotate, 0, index);
                  Array.Reverse(toRotate, index, toRotate.Length-index);
                  Array.Reverse(toRotate, 0, toRotate.Length);
              }
          

          在您的示例中,索引为 16。此代码处理奇数个项目,并且索引不在中间。使用类似于书中 toRotate={0,1,2,3,4,5,6,7} 和 index = 3 的示例 Rotate2 将产生 {3,4, 5,6,7,0,1,2}。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-08-28
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多