Как сдвинуть элементы массива
Вопрос
У меня есть массив из 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};
Кто-нибудь знает, как лучше всего сдвинуть элементы для создания отсортированного массива из оригинала?
Этот массив, кстати, привязан к другому массиву, в котором элементы не отсортированы по размеру одинаково, и его нужно сдвигать так же, как исходный, поэтому массив не следует сортировать по размеру, его нужно сдвинуть.
Решение
Итак, вам нужен второй массив с содержимым оригинала, но местами смещенным?Либо сделайте это явно:
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);
Другие советы
Учитывая жесткий характер проблемы, Array.Copy
:
int half = original.Length / 2;
Array.Copy(original, 0, sorted, half, half);
Array.Copy(original, half, sorted, 0, half);
А как насчет Linq:
int half = original.Length/2;
var sorted = original.Skip(half).Concat(original.Take(half)).ToArray();
Попытался ли ты:
Array.Sort(original);
Просто поменяйте местами элемент 0 и элемент 16, 1 и 17, 2 и 18..и т. д.
Хотите отсортировать один массив на основе значений, содержащихся в другом массиве того же размера?Если да, используйте следующее:
Array.Sort(keys, values);
Вот документация Array.Sort(ключи массива, элементы массива)
Ответы Джона Скита и Марка Грэвелла♦ дают правильное решение, но если вы не хотите выделять дополнительный массив, вы можете:
а) решить конкретную проблему (сдвинув вторую половину до первой половины) на месте:
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. Повернуть2 будет производить {3,4,5,6,7,0,1,2}.