矩阵花样遍历

矩阵顺时针遍历

题目:输入矩阵行和列,要求能够打印出从1开始顺时针自增的矩阵,以m=5,n=4为例,输出如下矩阵
1 2 3 4
14 15 16 5
13 20 17 6
12 19 18 7
11 10 9 8

重点:遵循的原则是一层一层去遍历,每一层有4提条边(顶top/右right/下bottom/左left),每一段的遍历遵循左闭右开的原则,如果遍历到最后一圈,发现只有一条边或者一个点,需要单独处理下
m=4,n=6,遍历如下:
在这里插入图片描述
m=5,n=3,遍历如下
在这里插入图片描述

代码实现

#include <iostream>
#include <vector>
using namespace std;

void showMatrix(int m, int n){
	vector<vector<int>> a(m, vector<int>(n,0));
	int left = 0, top = 0, right = n-1, bottom = m-1;
	int val = 1;
	while(left < right && top < bottom){
		// 顶部从左到右
		for(int k = left; k < right; k++){
			a[top][k] = val++;
		}

		// 右侧从上到下
		for(int k = top; k < bottom; k++){
			a[k][right] = val++;
		}

		// 底部从右到左
		for(int k = right; k > left; k--){
			a[bottom][k] = val++;
		}

		// 左侧从下到上
		for(int k = bottom; k > top; k--){
			a[k][left] = val++;
		}
		

		left += 1;
		right -= 1;
		top += 1;
		bottom -= 1;

	}
	
	if(left == right && top < bottom){ // 剩下一列待填充
		for(int k = top; k <= bottom; k++){
			a[k][left] = val++;
		}
	}else if(left < right && top == bottom){ // 剩下一行待填充
		for(int k = left; k <= right; k++){
			a[top][k] = val++;
		}
	}else if(left == right && top == bottom){ // 剩下一个点待填充
		a[left][top] = val++;
	}

	for(int i = 0; i < m; i++){
		for(int j = 0; j < n; j++){
			cout << a[i][j] << "\t";
		}
		cout << endl;
	}
}
 
int main()
{
    showMatrix(5,4);
    return 0;
}

输出结果

在这里插入图片描述

如果是 m == n 那就是正方形

给定一个正整数 n,生成一个包含 1 到 n 2 n^2 n2 总共 n 2 n^2 n2 各元素,且元素按顺时针顺序螺旋排列的正方形矩阵。例如 n=3
在这里插入图片描述

前面的代码里面的m都该成n就行,同时因为是正方形,最后一圈不存在只有一行或者一列,当n为奇数的时候,只剩下最中心的一个点没有填充,单独处理即可。

n=3
在这里插入图片描述
n=4

在这里插入图片描述

#include <iostream>
#include <vector>
using namespace std;

void showMatrix(int n){
	vector<vector<int>> a(n, vector<int>(n,0));
	int left = 0, top = 0, right = n-1, bottom = n-1;
	int val = 1;
	while(left < right && top < bottom){
		// 顶部从左到右
		for(int k = left; k < right; k++){
			a[top][k] = val++;
		}

		// 右侧从上到下
		for(int k = top; k < bottom; k++){
			a[k][right] = val++;
		}

		// 底部从右到左
		for(int k = right; k > left; k--){
			a[bottom][k] = val++;
		}

		// 左侧从下到上
		for(int k = bottom; k > top; k--){
			a[k][left] = val++;
		}
		

		left += 1;
		right -= 1;
		top += 1;
		bottom -= 1;

	}
	
//	if(left == right && top < bottom){ // 剩下一列待填充
//		for(int k = top; k <= bottom; k++){
//			a[k][left] = val++;
//		}
//	}else if(left < right && top == bottom){ // 剩下一行待填充
//		for(int k = left; k <= right; k++){
//			a[top][k] = val++;
//		}
//	}else if(left == right && top == bottom){ // 剩下一个点待填充
//		a[left][top] = val++;
//	}
	if(n % 2 == 1){  //  当n为奇数的时候,这里只剩一个点待填充,正方形不存在最后一行或者一列待填充的情况
		a[n/2][n/2] = val++;
	}

	for(int i = 0; i < n; i++){
		for(int j = 0; j < n; j++){
			cout << a[i][j] << "\t";
		}
		cout << endl;
	}
}
 
int main()
{
    showMatrix(3);
    return 0;
}

矩阵对角线遍历

题目:输入矩阵行和列,要求能够打印出从1开始对角线自增的矩阵,以m=5,n=4为例,输出如下矩阵
1		2		3		4	
14	15	16	5	
13	20	17	6	
12	19	18	7	
11	10	9		8

在这里插入图片描述

从最左上角开始,按对角线方式一直遍历到最右下角结束。到达边界就需要改变遍历顺序(向上或者向下),用个bool变量标识遍历顺序。
遵循原则:
往上:行-1,列+1;可能会超过上边界或者右边界,超过上边界,行+1,列不变,超过右边界,行+2,列-1
往下:行+1,列-1;可能会超过下边界或者左边界,超过下边界,行-1,列+2,超过左边界,行不变,列+1

遍历图如下:
在这里插入图片描述

#include <iostream>
#include <vector>
using namespace std;

void showMatrix(int m, int n){
	vector<vector<int>> a(m, vector<int>(n,0));
	bool up = true;
	int row = 0, col = 0;
	int val = 1;
	while(row < m || col < n){ // 没有到达最右下角位置,则一直循环
		if(0 <= row && row < m && col < n && 0 <= col){
			a[row][col] = val++;
		}
		
		if(up){ // 斜向上遍历 行-1,列+1
			row -= 1;
			col += 1;
			if(row < 0){  // 超过上边界
				row += 1; 
				up = false;  // 需要往斜向下遍历
			}else if(col > n-1){ // 超过右边界
				col -= 1;
				row += 2;
				up = false;   // 需要往斜向下遍历
			}
			
		}else{ // 斜向下遍历 行+1,列-1
			row += 1;
			col -= 1;
			if(row > m-1){ // 超过下边界
				row -= 1;
				col += 2;
				up = true; // 需要往斜向上遍历
			}else if(col < 0){ // 超过左边界
				col += 1;
				up = true; // 需要往斜向上遍历
			}
			
		}

	}

	for(int i = 0; i < m; i++){
		for(int j = 0; j < n; j++){
			cout << a[i][j] << "\t";
		}
		cout << endl;
	}
}
 
int main()
{
    showMatrix(3,5);
    return 0;
}

矩阵旋转

题目:输入方阵形状n,要求能够将方阵顺时针旋转90度,以n=4为例,变化如下矩阵
在这里插入图片描述

遵循原则:和螺旋矩阵一样,一层一层来;每层先把顶部行暂存起来,然后依次旋转复制

在这里插入图片描述

#include <iostream>
#include <vector>
using namespace std;

void show(vector<vector<int>> a){
	int n = a.size();
	for(int i = 0; i < n; i++){
		for(int j = 0; j < n; j++){
			cout << a[i][j] << "\t";
		}
		cout << endl;
	}
}

void showMatrix(vector<vector<int>> a){
	int n = a.size();
	int left = 0, right = n-1, top = 0, bottom = n-1;
	vector<int> topEage(n,0);  // 顶部暂存数组
	vector<int> tmp(n, 0);  // 取数据暂存
	while(left < right && top < bottom){
		// 暂存顶部边的数据,放到topEage数组中
		int i = 0;
		for(int k = left; k < right; k++){
			topEage[i] = a[top][k];
			i++;
		}
		i = 0;

		// 左边数据取出来,放到tmp中
		for(int k = bottom; k > top; k--){
			tmp[i] = a[k][left];
			i++;
		}
		// tmp复制到顶部边上
		i = 0;
		for(int k = left; k < right; k++){
			a[top][k] = tmp[i];
			i++;
		}

		cout << "copy to top" << endl;
		show(a);

		// 底部数据取出来,放到tmp中
		i = 0;
		for(int k = right; k > left; k--){
			tmp[i] = a[bottom][k];
			i++;
		}
		// tmp复制到左部边上
		i = 0;
		for(int k = bottom; k > top; k--){
			a[k][left] = tmp[i];
			i++;
		}

		cout << "copy to left" << endl;
		show(a);

		// 右部数据取出来,放到tmp中
		i = 0;
		for(int k = top; k < bottom; k++){
			tmp[i] = a[k][right];
			i++;
		}
		// tmp复制到底部边上
		i = 0;
		for(int k = bottom; k > top; k--){
			a[bottom][k] = tmp[i];
			i++;
		}

		cout << "copy to bottom" << endl;
		show(a);

		// 顶部数据在topEage中,复制到右部边上
		i = 0;
		for(int k = top; k < bottom; k++){
			a[k][right] = topEage[i];
			i++;
		}

		cout << "copy to right" << endl;
		show(a);


		left += 1;
		right -= 1;
		top += 1;
		bottom -= 1;
	}

	cout << "final" << endl;
	show(a);
}

vector<vector<int>> getMatrix(int n){  // 生成自增长螺旋矩阵
	vector<vector<int>> a(n, vector<int>(n, 0));
	int left = 0, right = n-1, top = 0, bottom = n-1;
	int val = 1;
	// left/right 是列维度
	// top/bottom 是行维度
	while(left < right && top < bottom){
		for(int k = left; k < right; k++){ // 顶部
			a[top][k] = val++;
		}
		for(int k = top; k < bottom; k++){ // 右部
			a[k][right] = val++;
		}
		for(int k = right; k > left; k--){ // 底部
			a[bottom][k] = val++;
		}
		for(int k = bottom; k > top; k--){ // 左部
			a[k][left] = val++;
		}
		left += 1;
		right -= 1;
		top += 1;
		bottom -= 1;
	}
	if(n%2==1){
		a[n/2][n/2] = val++;
	}
	return a;
}

 
int main()
{
    int n = 4;
    vector<vector<int>> a = getMatrix(n);
	cout << "start" << endl;
	show(a);
    showMatrix(a);
    return 0;
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值