Алгоритм, подобный этому, легче понять, если вы рисуете диаграмму, поэтому я сделал быстрый рис в Paint для демонстрации для матрицы 5x5: D
Внешний цикл for(int layer=0; layer < n/2; ++layer)
перебирает слои снаружи внутрь. Внешний слой (слой 0) изображен цветными элементами. Каждый слой фактически представляет собой квадрат элементов, требующих вращения. Для n = 5, layer будет принимать значения от 0 до 1, так как есть 2 слоя, так как мы можем игнорировать центральный элемент / слой, на который не влияет вращение. first и last относятся к первым и последним строкам / столбцам элементов слоя; например слой 0 содержит элементы из строки / столбца first = 0 до last = 4 и слой 1 из строки / столбца 1 в 3.
Затем для каждого слоя / квадрата внутренний цикл for(int i=first; i<last;++i)
вращает его, вращая 4 элемента в каждой итерации. Смещение показывает, как далеко мы по сторонам квадрата. Для нашего 5x5 ниже мы сначала поворачиваем красные элементы (смещение = 0), затем желтый (смещение = 1), затем зеленый и синий. Стрелки 1-5 демонстрируют 4-элементное вращение для красных элементов и 6+ для остальных, которые выполняются таким же образом. Обратите внимание, что 4-элементное вращение - это, по сути, циклический своп с 5 назначениями, при котором первое назначение временно откладывает элемент. Комментарий //save the top left of the matrix
для этого назначения вводит в заблуждение, поскольку matrix [first] [i] не обязательно является верхним левым краем матрицы или даже слоем в этом отношении. Также обратите внимание, что индексы строк / столбцов вращающихся элементов иногда пропорциональны смещению , а иногда пропорциональны его обратному последнему - смещению .
Мы перемещаемся по сторонам внешнего слоя (обозначены first = 0 и last = 4) таким образом, затем переходим на внутренний слой (first = 1 и last = 3) и делаем там то же самое. В конце концов, мы попали в центр, и мы закончили.