Статус: Эксперт
Группы: Участники
Зарегистрирован: 05.03.2015(UTC) Сообщений: 1,602  Откуда: Иркутская область Сказал(а) «Спасибо»: 110 раз Поблагодарили: 395 раз в 366 постах
|
Автор: ыволавыд  Решение интересное. Но как быть если в строке четное количество символов? Сч равно количеству элементов массива, писать в новый массив надо начиная с последнего элемента массива и надо остановиться когда элементы массива закончатся, поэтому запускается цикл следящий за состоянием переменной Сч, значение которой на каждой итерации цикла уменьшается на единицу. С начала записывается последний элемент массива с индексом Сч, потом с Сч-1 и так до тех пор пока Сч не станет равным 0. Что-то запутали. Говорим одно и тоже, но на своих языках. У Вас между проверкой условия цикла и обращением к элементу массива МассивДвоичныхДанных[Сч] стоит уменьшение Сч, то есть последняя итерация на входе имеет Сч=1, потом Сч уменьшается до 0 и обращается к МассивДвоичныхДанных[0], все сходится. Заметьте, что переменная Сч не станет отрицительной, поэтому из Сч<>0 часть Сч<0 никогда не сработает, достаточно написать Сч>0 в условии цикла. Пусть N число элементов массива, у меня вариант с нумерацией с 1 до N, у Вас с 0 до N-1. Что бы сделать из моего варианта 0 до N-1 надо просто вычесть единицу в 2 местах, вот так: Код:L:=A.length; // длина строки, поминаем как количество элементов, а не как номер последнего если нумерация с нуля!!!
j:=L-1; // номер последнего байта, нумерация с 0
L:=(L shr 1)-1; // середина строки
for i:=0 to L do begin // с 0 до середины
temp:=A[i];A[i]:=A[j];A[j]:=temp; // меняем A[i] и A[j]
dec(j); // это j:=j-1; или j--;
end;
Четное или нечетное число элементов массива значение не имеет в силу специфики оператора shr 1, это сдвиг числа вправо на 1 бит, для положительных или беззнаковых чисел эффект как если бы число поделили пополам, но еще и теряется значение последнего бита (то есть как целочисленное деление на 2 без округления, на Бэйсике кажется это записывается как "N \ 2", направление черты не опечатка). Смотрите что выходит:
Код:Четное количество элементов: пусть L=4, нумерация массива с 0 до 3, A[0] A[1] A[2] A[3]
j=4-1=3
L=(4 shr 1)-1=2-1=1
подставляем в цикл
for i:=0 to 1 do begin ... end;
итерация 0 (начальное значние j=3)
i=0
temp:=A[0]; //A[i]
A[0]:=A[3]; //A[i]:=A[j]
A[3]:=temp; //A[j]
j=j-1=2
итерация 1 (j стало 2)
i=i+1=1 // неявно в for
temp:=A[1]; //A[i]
A[1]:=A[2]; //A[i]:=A[j]
A[2]:=temp; //A[j]
j=j-1=1
конец цикла
Все элементы поменяны местами в случае четного числа элементов. Код:Нечетное количество элементов: пусть L=5, нумерация массива с 0 до 4, A[0] A[1] A[2] A[3] A[4]
j=5-1=4
L=(5 shr 1)-1=2-1=1
подставляем в цикл
for i:=0 to 1 do begin ... end;
итерация 0 (начальное значние j=4)
i=0
temp:=A[0]; //A[i]
A[0]:=A[4]; //A[i]:=A[j]
A[4]:=temp; //A[j]
j=j-1=3
итерация 1 (j стало 2)
i=i+1=1 // неявно в for
temp:=A[1]; //A[i]
A[1]:=A[3]; //A[i]:=A[j]
A[3]:=temp; //A[j]
j=j-1=2
конец цикла
Поменяны местами все элементы кроме A[2], но его и не надо менять - в случае нечетного числа элементов он остается на своем месте. На оптимальность естественно не претендую, так как у Вас по одной операции чтения и записи массива на итерацию, а у меня по 2 операции чтения и по 2 записи на итерацию, так что в среднем получается то же самое. У меня не нужен второй массив, но зато условно говоря, "портится" исходный массив, так что на практике сначала создается копия массива потом переворачивается копия. Разница будет только при нечетном количестве элементов, когда у меня один элемент вообще не трогается, а у Вас читаются/пишутся все. Разница такого порядка уже больше зависит от оптимизации компилятора. На ассемблере инвертирование порядка байт в массиве будет гораздо быстрее чем на высокоуровневых языках, потому как там уже есть копирование movsb из памяти по адресу esi в память по адресу edi по 1 байту и цикл repnz по ecx, надо только адрес записи edi уменьшать вместо увеличения.
Если можно приведите исходное и инвертированное в Base64, что бы убедиться что соединилось все правильно (что-то не доверяю Бейсику). Отредактировано пользователем 2 сентября 2019 г. 6:24:43(UTC)
| Причина: Не указана
|