C++矩阵常见操作及习题

本文详细介绍矩阵的基础知识,包括加法、减法、数乘、乘法和转置,并提供C++代码实现。通过实例讲解,帮助读者理解矩阵运算原理及实际应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 要熟练掌握矩阵的运算,首先需具有线性代数的知识:参考百度百科https://baike.baidu.com/item/%E7%9F%A9%E9%98%B5/18069

 

一、矩阵基础知识

矩阵运算包括矩阵的加法,减法,数乘,乘法、转置,共轭共轭转置

 

  矩阵加法:(只有同型矩阵之间才可以进行加法)

    

 

  矩阵的加法满足下列运算律(A,B,C都是同型矩阵):

 


  矩阵减法:(只有同型矩阵之间才可以进行减法)

 

 

矩阵数乘

  矩阵的数乘满足以下运算律:
  矩阵的加减法和矩阵的数乘合称矩阵的线性运算

 

  矩阵乘法:

  矩阵的加减法和矩阵的数乘合称矩阵的线性运算。

  C = AB

  将A, B, C分成相等大小的方块矩阵:

 

 


  C11=A11B11+A12B21                       

  C12=A11B12+A12B22                        

  C21=A21B11+A22B21                          

  C22=A21B12+A22B22                          

  示例:

 

 

  矩阵的转置:

  把矩阵A的行和列互相交换所产生的矩阵称为A的转置矩阵,这一过程称为矩阵的转置。

    

 

  矩阵的转置满足以下运算律:

 

 

 

  

 

 二、C++代码实现加法,减法,数乘,乘法,转置

1、加法,减法,数乘,乘法的实现

#include <iostream>

#include <malloc.h>
#include <stdio.h>
using namespace std;

 

typedef struct
{
//结构体
int row,col;
//二维指针,目的是动态分配内存
float **matrix;
} Matrix;

 

typedef struct
{
char *name;
char *number;
} Student;

 

Matrix CreateMatrix()
{
Matrix m;
int row,col;
cout << "输入行数与列数:" << endl;
cin >> row >> col;
float **enterMatrix ;
enterMatrix=(float**) malloc(row*sizeof(float*)) ;
for(int i=0; i<row; i++)
enterMatrix[i] = (float *)malloc(col * sizeof(float));
cout<<"输入你的矩阵:"<<endl;
for(int i=0; i<row; i++)
{
for(int j=0; j<col; j++)
{
cin >> enterMatrix[i][j];
}
}
m.col = col;
m.row = row;
m.matrix = enterMatrix;
return m;
}

 

//初始化一个行为row列为col矩阵
Matrix InitMatrix(int row,int col)
{
Matrix m;
float **matrix ;
matrix=(float**) malloc(row*sizeof(float*)) ;
for(int i=0; i<row; i++)
matrix[i] = (float *)malloc(col * sizeof(float));
for(int i=0; i<row; i++)
{
for(int j=0; j<col; j++)
{
matrix[i][j] = 0;
}
}
m.col = col;
m.row = row;
m.matrix = matrix;
return m;
}

//加法

Matrix add(Matrix m1, Matrix m2)

{
for(int i=0; i<m1.row; i++)
{
for(int j=0; j<m1.col; j++)
{
m1.matrix[i][j] = m1.matrix[i][j] +m2.matrix[i][j];
}
}
return m1;
}

 //减法

Matrix sub(Matrix m1, Matrix m2)
{
for(int i=0; i<m1.row; i++)
{
for(int j=0; j<m1.col; j++)
{
m1.matrix[i][j] = m1.matrix[i][j] -m2.matrix[i][j];
}
}
return m1;
}

 

int calRowCol(Matrix M1,Matrix M2,int row,int col)//row为M1的行 col为m2的列
{
int result = 0;
int same = M1.col;
for(int j=0; j<same; j++)
{
result+=M1.matrix[row][j]*M2.matrix[j][col];
}

 

return result;
}

 

//乘法
Matrix Mul(Matrix m1, Matrix m2)
{
Matrix result = InitMatrix(m1.row,m2.col);
for(int i=0; i<m1.row; i++)
{
for(int j=0; j<m2.col; j++)
{
result.matrix[i][j] = calRowCol(m1,m2,i,j);
}
}
return result;
}

 //数乘

Matrix numMul(Matrix m, int num)
{
cout<<"数值:"<<num<<endl;
for(int i=0; i<m.row; i++)
{
for(int j=0; j<m.col; j++)
{
m.matrix[i][j] = m.matrix[i][j]*num;
}
}
return m;
}

 //输出

Matrix printMatrix(Matrix m)

{
for(int i=0; i<m.row; i++)
{
for(int j=0; j<m.col; j++)
{
cout << m.matrix[i][j] << " ";
}
cout<<endl;
}
}

 

int main()
{
int num = 0;
do
{
cout<<"*************************************\n";
cout<<"* 菜单 *\n";
cout<<"* 1.矩阵相加 *\n";
cout<<"* 2.矩阵相减 *\n";
cout<<"* 3.矩阵相乘 *\n";
cout<<"* 4.矩阵数乘 *\n";
cout<<"* 5.退出 *\n";
cout<<"*************************************\n";
cin>>num;
if(1 == num|| 2 == num || 3 == num)
{
cout<<"请输入矩阵1"<<endl;
Matrix m1 = CreateMatrix();
cout<<"请输入矩阵2"<<endl;
Matrix m2 = CreateMatrix();
cout<<"两矩阵为"<<endl;
printMatrix(m1);
cout<<endl;
printMatrix(m2);
switch(num)
{
case 1:
{
if(m1.col!=m2.col || m1.row!=m2.row)
{
cout<<"行列不同"<<endl;
}
else{
cout<<"结果为:"<<endl;
printMatrix(add(m1,m2));
}
break;
}
case 2:
{

 

if(m1.col!=m2.col || m1.row!=m2.row)
{
cout<<"参数错误"<<endl;
}
else{
cout<<"结果为:"<<endl;
printMatrix(sub(m1,m2));
}
break;

 

}
case 3:
{
if(m1.col!=m2.row)
{
cout<<"参数错误"<<endl;
}
else{
cout<<"结果为:"<<endl;
printMatrix(Mul(m1,m2));
}
break;
}
default:
break;
}
}
else if(4 == num)
{
int number = 1;
cout<<"请输入矩阵"<<endl;
Matrix m = CreateMatrix();
cout<<"请输入数值"<<endl;
cin>>number;
cout<<"矩阵为:"<<endl;
printMatrix(m);
cout<<"数值为:"<<endl;
cout<<number<<endl;
printMatrix(numMul(m,number));
}
cout<<"按回车继续....";

 

getchar();
getchar();
system("cls");
}
while(1 == num|| 2 == num || 3 == num ||4 == num);
return 0;
}

2、给定一矩阵求其转置矩阵

  //n阶矩阵求转置,也就是沿着左对角线反转矩阵;a[i][j]  与 a[j][i] 对换。

#include<iostream>
using namespace std;
template<class T>
void swap(T* a, T* b)
{
T temp = a;
*a = *b;
*b = temp;
return;
}
template<class T>
void transpose(T& a, int rows)
{
for (int i = 0; i < rows; i++)
{
for (int j = i + 1; j < rows; j++)
{
swap(a[i][j], a[j][i]);
}
}
return;
}
int main()
{
int a[3][3] = { 1,2,3,4,5,6,7,8,9 };
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
cout << a[i][j] << " ";
}
cout << endl;
}
transpose(a, 3);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
cout << a[i][j] << " ";
}
cout << endl;
}
return 0;
}

 

//n * m矩阵的转置,行和列颠倒。

#include<iostream>
using namespace std;
template<class T>
void swap(T* a, T* b)
{
T temp = a;
*a = *b;
*b = temp;
return;
}
template<class T,class T1>
void transpose(T& a, T1& b,int rows,int cols)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
b[j][i] = a[i][j];
}
}
return;
}
int main()
{
int a[4][3] = { 1,2,3,4,5,6,1,2,3,4,5,6 };
int b[3][4] = { 0 };
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 3; j++)
{
cout << a[i][j] << " ";
}
cout << endl;
}
cout << endl;
transpose(a,b,4,3);
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
{
cout << b[i][j] << " ";
}
cout << endl;
}
return 0;
}

 

 应用实例

题目一——zigzag方式打印矩阵

用zigzag的方式打印矩阵,比如如下的矩阵
0 1 2 3
4 5 6 7
8 9 10 11
打印顺序为:0 1 4 8 5 2 3 6 9 10 7 11
我的问题主要出在了变量名上,二维数组a[i][j]里面,i是行,对应了直角坐标里面的y,j是列,对应了直角坐标里面的x。以后二维矩阵的题,我变量名都取行列吧,再也不取xy了,绕晕了,啊啊啊啊啊。

思路:

用两个指针A和B,用(xa,ya)表示A的位置,(xb,yb)表示B的位置。依次移动这两个指针,使得他们每次都处在一条斜线上。置于来回打印,可以用一个bool变量来控制打印方向即可。

 

 

 

代码里还是有很多边界需要考虑的,比如print函数里面的while循环,两个变量的比较顺序放反了,就会导致你少打印点东西,具体例子看代码的注释

/*
用zigzag的方式打印矩阵,比如如下的矩阵
0 1 2 3
4 5 6 7
8 9 10 11
打印顺序为:0 1 4 8 5 2 3 6 9 10 7 11
*/
#include<iostream>
#include<vector>
using namespace std;

void helper(vector<vector<int>>&num, int av, int ah, int bv, int bh, bool flag){
//打印顺序,先左上(flag=true时),后右下(flag=false时)
if(!flag){
//向左下方打印(坐标和二维矩阵的是不一样的,阿西吧)
//从(0,2)走到(2,0)
while(ah!=bh-1)
cout<<num[av++][ah--]<<endl;
}else{
//向左上方打印
//从(1,0)到(0,1)
while(bv!=av-1)
cout<<num[bv--][bh++]<<endl;
}
}

void Print(vector<vector<int>>&num){
if(num.size()==0) return;

int av=0, ah=0, bv=0, bh=0;
bool flag=true;
int hor=num[0].size()-1, ver=num.size()-1;

while(av!=(ver+1)){
helper(num, av, ah, bv, bh, flag);
//av为什么写在ah的上面?思考情况:
//ah=hor-1时,如果ah写在上面,则ah=ah+1,此时ah=hor,
//本来应该指向矩阵右上角的,结果av一看ah=hor了,就猥琐的执行了 av=av+1
av=ah==hor?av+1:av;
ah=ah==hor?ah:ah+1;

bh=bv==ver?bh+1:bh;
bv=bv==ver?bv:bv+1;
flag=!flag;
}
}

int main(){
vector<vector<int>>num={{0,1,2,3},{4,5,6,7},{8,9,10,11}};
Print(num);
return 0;
}
 

 题目二——用螺旋的方式打印矩阵,比如如下的矩阵

用螺旋的方式打印矩阵,比如如下的矩阵
0 1 2 3
4 5 6 7
8 9 10 11
打印顺序为:0 1 2 3 7 11 10 9 8 4 5 6
不要跟着打印的线路走,宏观去看,每次都是打印最外面的一圈(如下图),所以可以设置两个点,一个指向矩形的左上角(ar和ac分别表示a行和a列),一个指向矩形的右下角。每次打印完一圈。就把左上角的向右下角移动一位,同理右上角的指针向左上角移动一位。

打印会遇到两个特殊情况

1、ar=br 即两个指针指向了同一行元素(例子看下侧实现代码的helper函数)

2、ac=bc 即两个指针指向了同一列元素(例子看下侧实现代码的helper函数)

对于这两种情况,在打印的时候要区分出来

 

 

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

void helper(vector<vector<int>>& matrix,
vector<int>&res, int ar, int ac, int br, int bc){
//说明此时要打印一条水平线
/*
1234
5678
1234
当打印中间的67的时候,会出现这种情况
*/
if(ar==br){
while(ac<bc+1){
res.push_back(matrix[ar][ac++]);
}
//此时打印一列的情况
/*
123
456
789
123
当打印中间的那一竖58的时候,会出现该种情况
*/
}else if(ac==bc){
while(ar<br+1){
res.push_back(matrix[ar++][ac]);
}
}else{
int hor=ac, ver=ar;
//打印上面的横向边框
while(hor<bc){
res.push_back(matrix[ar][hor++]);
}
//打印右侧的纵向边框
while(ver<br){
res.push_back(matrix[ver++][hor]);
}
//打印下方的横向边框
while(hor>ac){
res.push_back(matrix[ver][hor--]);
}
//打印左侧的竖向边框
while(ar<ver){
res.push_back(matrix[ver--][hor]);
}
}
}

vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int>res;
if((matrix.size()==0)||(matrix[0].size()==0)) return res;

int ar=0, ac=0, br=matrix.size()-1, bc=matrix[0].size()-1;
while(1){
//打印边框的函数
helper(matrix, res,ar,ac,br,bc);
//打印之后移动指针,以便于打印内层的边框
ar++;
ac++;
br--;
bc--;
if((ar>br)||(ac>bc)) break;
}
for(auto i:res)
cout<<i<<" ";
return res;
}

int main(){
vector<vector<int>>matrix={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
spiralOrder(matrix);
cout<<endl;
return 0;
}
 

这题是leetcode 54题

上AC代码

class Solution {
public:
void helper(vector<vector<int>>& matrix,
vector<int>&res, int ar, int ac, int br, int bc){
//说明此时要打印一条水平线(ar=br的情况)
if(ar==br){
while(ac<bc+1){
res.push_back(matrix[ar][ac++]);
}
}else if(ac==bc){
while(ar<br+1){
res.push_back(matrix[ar++][ac]);
}
}else{
int hor=ac, ver=ar;
while(hor<bc){
res.push_back(matrix[ver][hor++]);
}
while(ver<br){
res.push_back(matrix[ver++][hor]);
}
while(hor>ac){
res.push_back(matrix[ver][hor--]);
}
while(ar<ver){
res.push_back(matrix[ver--][hor]);
}
}
}

vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int>res;
if((matrix.size()==0)||(matrix[0].size()==0)) return res;

//设置两个角的坐标
int ar=0, ac=0, br=matrix.size()-1, bc=matrix[0].size()-1;
while(1){
helper(matrix, res,ar,ac,br,bc);
ar++;
ac++;
br--;
bc--;
if((ar>br)||(ac>bc)) break;
}
return res;
}
};
 

 题目三——给定一个正方形矩阵,只用有限几个变量,实现矩阵中每个位置的数顺时针转动

给定一个正方形矩阵,只用有限几个变量,实现矩阵中每个位置的数顺时针转动
90度,比如如下的矩阵
0 1 2 3
4 5 6 7
8 9 10 11
12 13 14 15
矩阵应该被调整为:
12 8 4 0
13 9 5 1
14 10 6 2
15 11 7 3


思路

  还是要宏观,假设一行有k个元素,这个矩阵里面的所有元素可以分成 k-1 组,每组四个元素。前提,这个矩阵一定是正方形,不是正方形你没办法转。对应的第 i 组的地个点的坐标为m[a][b+1] , m[a+i][d] ,  m[c][d-i] ,  m[c-i][b]. 每次旋转的时候,就是把这四个位置的值交换即可。

 

 

 

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

void helper(vector<vector<int>>&matrix, int a, int b, int c, int d){
int temp=0;
int time=d-c;
for(int i=0; i<time; i++){
temp=matrix[c-i][b];
matrix[c-i][b]=matrix[c][d-i];
matrix[c][d-i]=matrix[a+i][d];
matrix[a+i][d]=matrix[a][b+i];
matrix[a][b+i]=temp;
}
}

void rotate(vector<vector<int>>&matrix){
int a=0, b=0, c=matrix.size()-1, d=matrix[0].size()-1;
while(a<=c&&b<=d)
helper(matrix, a++, b++, c--, d--);
}

int main(){
vector<vector<int>>matrix={{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
rotate(matrix);
return 0;
}
 

这题是leetcode 48 旋转图像
class Solution {
public:
void helper(vector<vector<int>>& matrix, int a, int b, int c, int d){
int temp=0;
//将四个点的元素相互交换
for(int i=0; i<d-b; i++){
temp=matrix[c-i][b];
matrix[c-i][b]=matrix[c][d-i];
matrix[c][d-i]=matrix[a+i][d];
matrix[a+i][d]=matrix[a][b+i];
matrix[a][b+i]=temp;
}
}

void rotate(vector<vector<int>>& matrix) {
int a=0, b=0, c=matrix.size()-1, d=matrix[0].size()-1;
//选定四个点,开始转框
while(a<=c&&b<=d)
helper(matrix, a++,b++,c--,d--);
}
};

题目四:矩阵转置

给定一个矩阵 A, 返回 A 的转置矩阵。

矩阵的转置是指将矩阵的主对角线翻转,交换矩阵的行索引与列索引。

 

示例 1:

输入:[[1,2,3],[4,5,6],[7,8,9]] 输出:[[1,4,7],[2,5,8],[3,6,9]]

示例 2:

输入:[[1,2,3],[4,5,6]] 输出:[[1,4],[2,5],[3,6]]

思路:比较简单,但要注意对矩阵的初始化,如果不初始化会报错--》reference binding to null pointer of type ‘struct value_type‘

class Solution { public: vector<vector<int>> transpose(vector<vector<int>>& A) { if(A.size()==0){ return A ; } vector<vector<int>> Ar(A[0].size()); for (int i = 0; i < Ar.size(); i++) Ar[i].resize(A.size()); for (int i = 0; i<A[0].size(); i++) { for (int j = 0; j<A.size(); j++) { Ar[i][j] = A[j][i]; } } return Ar ; } };

参考:https://blog.csdn.net/qq_29996285/article/details/85221861
https://blog.csdn.net/u011463794/article/details/85223844

转载于:https://www.cnblogs.com/llb1246489954/p/10917296.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值