Как сдвинуть элементы массива - PullRequest
1 голос
/ 19 апреля 2009

У меня есть массив из 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};

Кто-нибудь знает, как лучше всего сместить элементы для создания отсортированного массива из оригинала?

Этот массив, кстати, привязан к другому массиву, в котором элементы не отсортированы по размеру таким же образом и должны быть смещены так же, как оригинал, чтобы массив не сортировался по размеру, оно должно быть сдвинуто .

Ответы [ 7 ]

9 голосов
/ 19 апреля 2009

Итак, вы хотите второй массив с содержимым оригинала, но смещенными местами? Либо сделайте это явно:

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);
3 голосов
/ 19 апреля 2009

Учитывая жесткий характер проблемы, Array.Copy:

        int half = original.Length / 2;
        Array.Copy(original, 0, sorted, half, half);
        Array.Copy(original, half, sorted, 0, half);
2 голосов
/ 19 апреля 2009

Как насчет в Linq:

int half = original.Length/2;
var sorted = original.Skip(half).Concat(original.Take(half)).ToArray();
0 голосов
/ 17 апреля 2013

Ответы Джона Скита и Марка Гравелла ♦ дают правильное решение, но если вы не хотите выделять дополнительный массив, вы можете:

а) решить конкретную проблему (перенести 2-ю половину на 1-ю половину):

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;
        }
    }

Обратите внимание, что этот код не может работать с массивом с нечетным числом элементов.

б) вы можете применить алгоритм векторного смещения, который я знаю из «Жемчуга программирования» Джона Бентли:

 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}.

0 голосов
/ 19 апреля 2009

Хотите отсортировать один массив на основе значений, содержащихся в другом массиве того же размера? Если это так, используйте следующее:

Array.Sort(keys, values);

Вот документация Array.Sort (ключи массива, элементы массива)

0 голосов
/ 19 апреля 2009

Вы пробовали:

Array.Sort(original);
0 голосов
/ 19 апреля 2009

Просто поменяйте местами элемент 0 и элемент 16, 1 и 17, 2 и 18 ... и т. Д.

...