【C++】矩阵翻转/n*n的矩阵旋转

刷题时被矩阵的旋转操作卡了n次了,决定写篇博客总结一下

思路参考:第40次CSP认证前四题 - Oaths - 博客园https://www.cnblogs.com/oaths/articles/19327767

这位大佬的实现个人感觉是比较符合直觉的(也比较好记)

翻转

矩阵坐标从(1,1)开始

翻转第x0到第x1行,第y0到第y1列的子矩阵,oi=1即上下翻转,oi=-1就左右翻转

cpp 复制代码
void fan_zhuan(int x0, int y0, int x1, int y1, int oi){
    if(oi == 1){ //上下翻转 
        while(x0 < x1){
            for(int i = y0; i <= y1; i ++ ){
                swap(a[x0][i], a[x1][i]); 
            }
            x0 ++ ; x1 -- ;
        }
    }
    else{//左右翻转
        while(y0 < y1){
            for(int i = x0; i <= x1; i ++ ){
                swap(a[i][y0], a[i][y1]);
            }
            y0 ++ ; y1 -- ;
        }
    }
}

旋转

注意:逆时针转i次90度==顺时针转4-i次90度;此处代码实现顺时针旋转

a为原矩阵,b为辅助矩阵,如果是旋转整个边长为l的正方形矩阵,公式为:

  • 顺时针转90度:b[j][l-i+1] = a[i][j];
  • 顺时针转180度:b[l-i+1][l-j+1] = a[i][j];
  • 顺时针转270度:b[l-j+1][i] = a[i][j];

只旋转左上角为(x,y),边长为l的l*l小矩阵,只需在a的下标加上偏移量,小矩阵第i行,即原矩阵的x+i-1行,小矩阵的第j列,即原矩阵的y+j-1行

  • 顺时针转90度:b[j][l-i+1] = a[x+i-1][y+j-1];
  • 顺时针转180度:b[l-i+1][l-j+1] = a[x+i-1][y+j-1];
  • 顺时针转270度:b[l-j+1][i] = a[x+i-1][y+j-1];
cpp 复制代码
/*
左上角坐标(x,y), 边长l,顺时针旋转90度*t次
*/
void  xuan_zhuan(int x,int y,int l,int t) { //time 次数 
	char b[N][N]; //辅助矩阵,坐标从(1,1)开始 只存需要旋转的小矩阵 
	if(t==0) return; //旋转0次 
	if(t==1) //顺时针转90度 90*1
	    for (int i = 1; i <= l; i++) {
	        for (int j = 1; j <= l; j++) {
	            b[j][l-i+1] = a[x+i-1][y+j-1];
	        }
    }
	else if(t==2){ //顺时针转180度 90*2次  
	    for (int i = 1; i <= l; i++)
	        for (int j = 1; j <= l; j++) {
	            b[l-i+1][l-j+1] = a[x+i-1][y+j-1];
	        }    	
	}
	else if(t==3){//顺时针转270度 90*3次
	    for (int i = 1; i <= l; i++) 
	        for (int j = 1; j <= l; j++) {
	            b[l-j+1][i] = a[x+i-1][y+j-1];
	        }    			
	} 
    
    //复制回去 
//    for(int i = 1; i <= l ; i ++ )
//        for(int j = 1 ; j <= l; j ++ ){
//            a[x + i - 1][y + j - 1] = b[i][j];
//        }

//    常数优化:使用 memcpy 进行整行拷贝
    for (int i = 1; i <= l; i++) {
        memcpy(&a[x + i - 1][y], &b[i][1], l*sizeof(char)); //memcpy(目标地址, 源地址, 字节数)
    }
} 

测试代码:

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
const int N=405;
char a[N][N]; //1~N行 1~ 列

int z; //正方形边长 

void print()
{
	for(int i=1;i<=z;i++){
		for(int j=1;j<=z;j++)
			cout<<a[i][j];
		cout<<endl;
	}
}

/*
翻转第x0到第x1行,第y0到第y1列的矩阵,oi=1即上下翻转,oi=-1就左右翻转 
*/
void fan_zhuan(int x0, int y0, int x1, int y1, int oi){
    if(oi == 1){ //上下翻转 
        while(x0 < x1){
            for(int i = y0; i <= y1; i ++ ){
                swap(a[x0][i], a[x1][i]); 
            }
            x0 ++ ; x1 -- ;
        }
    }
    else{//左右翻转
        while(y0 < y1){
            for(int i = x0; i <= x1; i ++ ){
                swap(a[i][y0], a[i][y1]);
            }
            y0 ++ ; y1 -- ;
        }
    }
    cout<<"======="<<endl; 
	print();
	cout<<"======="<<endl; 
}

/*
左上角坐标(x,y), 边长l,顺时针旋转90度*t次
*/
void  xuan_zhuan(int x,int y,int l,int t) { //time 顺时针转90度的次数 
	char b[l+5][l+5]; //辅助矩阵,坐标从(1,1)开始,只存需要旋转的小矩阵 
	if(t==0) return; //旋转0次 
	if(t==1) //顺时针转90度 90*1
	    for (int i = 1; i <= l; i++) {
	        for (int j = 1; j <= l; j++) {
	            b[j][l-i+1] = a[x+i-1][y+j-1];
	        }
    }
	else if(t==2){ //顺时针转180度 90*2次  
	    for (int i = 1; i <= l; i++)
	        for (int j = 1; j <= l; j++) {
	            b[l-i+1][l-j+1] = a[x+i-1][y+j-1];
	        }    	
	}
	else if(t==3){//顺时针转270度 90*3次
	    for (int i = 1; i <= l; i++) 
	        for (int j = 1; j <= l; j++) {
	            b[l-j+1][i] = a[x+i-1][y+j-1];
	        }    			
	} 
    
    //复制回去 
//    for(int i = 1; i <= l ; i ++ )
//        for(int j = 1 ; j <= l; j ++ ){
//            a[x + i - 1][y + j - 1] = b[i][j];
//        }

//    常数优化:使用 memcpy 进行整行拷贝
    for (int i = 1; i <= l; i++) {
        memcpy(&a[x + i - 1][y], &b[i][1], l*sizeof(char)); //memcpy(目标地址, 源地址, 字节数)
    }

	cout<<"======="<<endl; 
	print();
	cout<<"======="<<endl; 
} 

void solve()
{
	cin>>z;
	for(int i=1;i<=z;i++)
	{
		string s; cin>>s;
		for(int j=1;j<=z;j++)
			a[i][j]=s[j-1];		
	}
//	print();
	fan_zhuan(1,1,4,4,1); //上下翻转 
	fan_zhuan(1,1,4,4,-1); //左右翻转- 
	xuan_zhuan(1,1,3,1); //1 1 3 1 
}

int main()
{
	ios::sync_with_stdio(0),cin.tie(0);
	solve();
	return 0;
}
/*
4
ABCD
EFGH
IJKL
MNOP

*/ 
相关推荐
田梓燊6 小时前
力扣:23.合并 K 个升序链表
算法·leetcode·链表
re林檎7 小时前
算法札记——4.27
算法
小白小宋7 小时前
【PUSCH第三期】5G NR QC-LDPC编码深度解析:从协议校验矩阵构造到MATLAB完整实现
5g·matlab·矩阵
数据牧羊人的成长笔记7 小时前
逻辑回归与Softmax回归
算法·回归·逻辑回归
郑州光合科技余经理8 小时前
同城O2O海外版二次开发实战:从支付网关到配送算法
开发语言·前端·后端·算法·架构·uni-app·php
张健11564096489 小时前
使用信号量限制并发数量
开发语言·c++
jc06209 小时前
6.1云原生之Docker
c++·docker·云原生
d111111111d11 小时前
STM32-UART封装问题解析
笔记·stm32·单片机·嵌入式硬件·学习·算法
叶子野格11 小时前
《C语言学习:指针》12
c语言·开发语言·c++·学习·visual studio
Jiangxl~12 小时前
IP数据云如何为不同行业提供精准IP查询与风险防控解决方案?
网络·网络协议·tcp/ip·算法·ai·ip·安全架构