数据结构预算法(六) 数组和矩阵(1)
数组:
抽象数据类型:
数组的操作:
1.存值 get(index)
2.取值 set(index, value)
这两个操作定义了抽象数据类型array
c++数组的索引,且数组时c++的标准数据结构
行主映射和列主映射 :
数组的应用需要将数组的元素序列化,按照一维排列,因为数组元素一次只能输出或者输入一个。因此必须确定一个输入输出的顺序(即映射关系)。
不规则的二维数组:
当数组的每行的元素个数不相等的 时候,数组称为不规则数组。不规则数组元素的访问方式与规则数组一样;
#include <iostream> using namespace std; int main(int argc, char *argv[]) { // cout<<"Hello C-Free!"<<endl; int numberOfRows = 5; // 数组的行数 // 定义每一行的长度 int length[5] = {6, 3, 4, 2, 7}; int** irregular_array = new int* [numberOfRows]; // 指向指针的指针 for(int i=0; i<numberOfRows; i++) { irregular_array[i] = new int[length[i]]; } // 初始化数组 for(int i=0; i<numberOfRows; i++) { for(int j=0; j<length[i]; j++) { irregular_array[i][j] = (i+j)*2; } } // 输出数组; for(int i=0; i<numberOfRows; i++) { for(int j=0; j<length[i]; j++) { cout << irregular_array[i][j] << " "; } cout << endl; } cout << "irregular_array[1][2] is " << irregular_array[1][2] << endl; return 0; }
矩阵
即数表,同城用来组织数据.定义matrix类,将二维矩阵映射到一维数组中。
注:c++中标准异常类是定义在标准命名空间中的,所以需要using namespace std.
将矩阵按照行主映射存储到一维数组中,注意矩阵的索引是从1开始,数组的是从0开始,需要转换;
matrix类的定义:matrix.h文件(模板类,定义和实现放在同一个文件中)
#ifndef MATRIX_H #define MATRIX_H #include <iostream> #include <stdexcept> // 包含C++中标准异常类 #include <string> using namespace std; // 定义matrix类 template<typename T> class matrix { private: int col; int row; T* element; // 存储矩阵元素,将矩阵映射到一维数组中 //采用行主次序 public: matrix(int row=1, int col=1); // 构造方法 matrix(const matrix<T>& mat); // copy constructor ~matrix(); // 析构函数 // 定义矩阵的一些操作 int rows() const; int cols() const; T& operator()(int i, int j) const; matrix<T>& operator=(const matrix<T>& mat); matrix<T> operator+(); matrix<T> operator+(const matrix<T>& mat); // 矩阵加法 matrix<T> operator-(); matrix<T> operator-(const matrix<T>& mat); // 矩阵减法 matrix<T> operator*(const matrix<T>& mat) const; // 矩阵乘法 matrix<T> operator+=(const T num); void print_matrix() const; // 输出矩阵 }; template<typename T> matrix<T>::matrix(int row, int col) { // 判断矩阵的合法性 if(row<=0 || col<=0) { throw runtime_error("Rows and cols must > 0"); } // 创建矩阵 this->row = row; this->col = col; element = new T[row*col]; } template<typename T> matrix<T>::matrix(const matrix<T>& mat) { row = mat.rows(); col = mat.cols(); this->element = new T[row*col]; for(int i=0; i<row*col; i++) { element[i] = mat.element[i]; } } template<typename T> matrix<T>::~matrix() { delete [] element; } template<typename T> int matrix<T>::rows() const { return row; } template<typename T> int matrix<T>::cols() const { return col; } /* template<typename T> T& matrix<T>::operator()(int i, int j) //矩阵下表的最最小值是1 { int tmp = col*(i-1)+(j-1); return element[tmp]; }*/ template<typename T> matrix<T>& matrix<T>::operator=(const matrix<T>& mat) { if(this!=&mat) // 不能复制自己 { delete [] element; // 将原来的element删除 row = mat.row; col = mat.col; element = new T [row*col]; // 复制元素 for(int i=0; i<(row*col); i++) { element[i] = mat.element[i]; } } return *this; } // 用()表示矩阵索引 template<typename T> T& matrix<T>::operator()(int i, int j) const { if(i>row || i<1 || j>col || j<1) { //throw invalid_argument("Matrix index out of bounds"); } return element[col*(i-1)+(j-1)]; } template<typename T> matrix<T> matrix<T>::operator+() { return *this; } //定义矩阵加法 template<typename T> matrix<T> matrix<T>::operator+(const matrix<T>& mat) { // 先判断矩阵的维度 if(col!=mat.cols() || row!=mat.rows()) { //throw runtime_error("The matrix size mismatch"); } matrix<T> w(row, col); // 定义一个新的矩阵 for(int i=0; i<row*col; i++) { w.element[i] = element[i] + mat.element[i]; } return w; } template<typename T> matrix<T> matrix<T>::operator-() { matrix<T> tmp(row, col); for(int i=0; i<row*col; i++) { tmp.element[i] = -element[i]; } return tmp; } // 定义矩阵减法 template<typename T> matrix<T> matrix<T>::operator-(const matrix<T>& mat) { if(col!=mat.cols() || row!=mat.rows()) { //throw runtime_error("The matrix size mismatch"); } matrix<T> w(row, col); // 定义一个新的矩阵 for(int i=0; i<row*col; i++) { w.element[i] = element[i] - mat.element[i]; } return w; } template<typename T> matrix<T> matrix<T>::operator+=(const T num) { matrix<T> w(row, col); for(int i=0; i<row*col; i++) { w.element[i] = element[i] +num; } return w; } //定义矩阵乘法 template<typename T> matrix<T> matrix<T>::operator*(const matrix<T>& mat) const { // 先判断矩阵的维度 if(col!=mat.rows()) { throw runtime_error("Matrix size mismatch"); } matrix<T> w(row, mat.col); for(int i=1; i<=row; i++) { for(int j=1; j<=mat.col; j++) { T sum = element[col*(i-1)+(1-1)] * mat(1, j); // 注意这里的处理方法 。先直接计算第一项,相当于给sum赋初值,因为这里的sum不能初始化为0 for(int k=2; k<=col; k++) // k从2开始 { sum += element[col*(i-1)+(k-1)] * mat(k, j); } w(i, j) = sum; } } return w; } template<typename T> void matrix<T>::print_matrix() const { for(int i=1; i<=row; i++) { for(int j=1; j<=col; j++) { cout << element[col*(i-1)+(j-1)] << " "; } cout << endl; } cout << endl; } #endif
测试代码1;
#include <iostream> #include "E:\back_up\code\c_plus_code\matrix\external_file\matrix.h" //#include <stdexcept> using namespace std; int main(int argc, char *argv[]) { cout<<"Hello C-Freesdf!"<<endl; matrix<int> m1(2,2); for(int i=1; i<=2; i++) { for(int j=1; j<=2; j++) { m1(i,j) = i+2*j; } } matrix<int> m2; m2 = -m1; m1.print_matrix(); cout << "---测试 operator- ----" << endl; m2.print_matrix(); matrix<int> m3; m3 = m2+m1; matrix<int> m4; m4 = m1-m2; cout << "---测试 operator+ ----" << endl; m3.print_matrix(); cout << "---测试 operator- ----" << endl; m4.print_matrix(); matrix<int> m5; m5 = m3 += 4; cout << "---测试 operator+= ----" << endl; m5.print_matrix(); // 矩阵乘法; matrix<int> m6(2,3); for(int i=1; i<=2; i++) { for(int j=1; j<=3; j++) { m6(i,j)= (i-1)*3+j; } } matrix<int> m7(3,2); for(int i=1; i<=3; i++) { for(int j=1; j<=2; j++) { m7(i,j) = (i-1)*2+j; } } m6.print_matrix(); m7.print_matrix(); matrix<int> m8; try // 添加异常捕获代码; { m8 = m6*m7; cout << "---测试 operator* ----" << endl; m8.print_matrix(); } catch(runtime_error& ex) { cout << "Exception: " << ex.what() << endl; } return 0; }
测试结果1:
测试代码2:main.cpp
#include <iostream> #include "E:\back_up\code\c_plus_code\matrix\external_file\matrix.h" //#include <stdexcept> using namespace std; int main(int argc, char *argv[]) { cout<<"Hello C-Freesdf!"<<endl; matrix<int> m1(2,2); for(int i=1; i<=2; i++) { for(int j=1; j<=2; j++) { m1(i,j) = i+2*j; } } matrix<int> m2; m2 = -m1; m1.print_matrix(); cout << "---测试 operator- ----" << endl; m2.print_matrix(); matrix<int> m3; m3 = m2+m1; matrix<int> m4; m4 = m1-m2; cout << "---测试 operator+ ----" << endl; m3.print_matrix(); cout << "---测试 operator- ----" << endl; m4.print_matrix(); matrix<int> m5; m5 = m3 += 4; cout << "---测试 operator+= ----" << endl; m5.print_matrix(); // 矩阵乘法; matrix<int> m6(2,3); for(int i=1; i<=2; i++) { for(int j=1; j<=3; j++) { m6(i,j)= (i-1)*3+j; } } matrix<int> m7(2,2); for(int i=1; i<=2; i++) { for(int j=1; j<=2; j++) { m7(i,j) = (i-1)*2+j; } } m6.print_matrix(); m7.print_matrix(); matrix<int> m8; try // 添加异常捕获代码; { m8 = m6*m7; cout << "---测试 operator* ----" << endl; m8.print_matrix(); } catch(runtime_error& ex) { cout << "Exception: " << ex.what() << endl; } return 0; }
测试结果2:
复杂度分析
对matrix类的扩充:
1.添加tranpose()方法,实现矩阵转置
template<typename T> matrix<T> matrix<T>::tranpose() const { matrix<T> tmp(col, row); // 存放转置后的矩阵 for(int i=1; i<=row; i++) { for(int j=1; j<=col; j++) { tmp(j,i) = element[col*(i-1)+(j-1)]; } } return tmp; }
测试代码:
cout << "---测试 transpose ----" << endl; matrix<int> m9; m9 = m8.tranpose(); m9.print_matrix();
结果:
2.添加自定义异常类到matrix类中:
需求:
1.当访问矩阵的索引值超过矩阵的实际大小的时候,应该抛出异常,这一功能由index_OutOf_Bound异常类实现
indexException.h文件: 基类是标准异常类out_of_range
// 自定义异常类 #ifndef INDEX_EXCEPTION_H #define INDEX_EXCEPTION_H #include <iostream> #include <stdexcept> using namespace std; class index_OutOf_Bound: public out_of_range // 矩阵索引超过范围 { private: int matrix_row; int matrix_col; public: index_OutOf_Bound(int row, int col):out_of_range("The matrix index out of bound") // 自定义异常类的构造方法调用基类的构造方法 { this->matrix_row = row; this->matrix_col = col; } void display_exception_info() const { cout << "Error detail" << endl; cout << "Matrix index (" << matrix_row << "," << matrix_col << ")" << " is out of bound" << endl; } }; #endif
2.当两个矩阵做加减乘的时候,如果维度不匹配,则抛出异常,这一功能由size_mismatch_exception类实现。
sizeMismatch文件:基类是标准异常类logic_error
// 自定义异常类 #ifndef SIZE_MISMATCH_EXCEPTION #define SIZE_MISMATCH_EXCEPTION #include <iostream> #include <stdexcept> using namespace std; class size_mismatch_exception: public logic_error { private: int a_row, a_col; int b_row, b_col; public: size_mismatch_exception(int a_row, int a_col, int b_row, int b_col): logic_error("Matrix size mismatch") { this->a_row = a_row; this->a_col = a_col; this->b_row = b_row; this->b_col = b_col; } void diaplay_error_detail() const { cout << "Error detail" << endl; cout << "A matrix size (" << a_row <<"," << a_col << ")" << " dose not match a matrix size (" << b_row << "," << b_col << ")" << endl; } }; #endif
matrix.h文件:
#ifndef MATRIX_H #define MATRIX_H #include <iostream> #include <stdexcept> // 包含C++中标准异常类 #include <string> #include "E:\back_up\code\c_plus_code\matrix\external_file\indexException.h" // 异常类文件 #include "E:\back_up\code\c_plus_code\matrix\external_file\sizeMismatch.h" using namespace std; // 定义matrix类 template<typename T> class matrix { private: int col; int row; T* element; // 存储矩阵元素,将矩阵映射到一维数组中 //采用行主次序 public: matrix(int row=1, int col=1); // 构造方法 matrix(const matrix<T>& mat); // copy constructor ~matrix(); // 析构函数 // 定义矩阵的一些操作 int rows() const; int cols() const; T& operator()(int i, int j) const; matrix<T>& operator=(const matrix<T>& mat); matrix<T> operator+(); matrix<T> operator+(const matrix<T>& mat); // 矩阵加法 matrix<T> operator-(); matrix<T> operator-(const matrix<T>& mat); // 矩阵减法 matrix<T> operator*(const matrix<T>& mat) const; // 矩阵乘法 matrix<T> operator+=(const T num); matrix<T> tranpose() const; void print_matrix() const; // 输出矩阵 }; template<typename T> matrix<T>::matrix(int row, int col) { // 判断矩阵的合法性 if(row<=0 || col<=0) { throw runtime_error("Rows and cols must > 0"); } // 创建矩阵 this->row = row; this->col = col; element = new T[row*col]; } template<typename T> matrix<T>::matrix(const matrix<T>& mat) { row = mat.rows(); col = mat.cols(); this->element = new T[row*col]; for(int i=0; i<row*col; i++) { element[i] = mat.element[i]; } } template<typename T> matrix<T>::~matrix() { delete [] element; } template<typename T> int matrix<T>::rows() const { return row; } template<typename T> int matrix<T>::cols() const { return col; } /* template<typename T> T& matrix<T>::operator()(int i, int j) //矩阵下表的最最小值是1 { int tmp = col*(i-1)+(j-1); return element[tmp]; }*/ template<typename T> matrix<T>& matrix<T>::operator=(const matrix<T>& mat) { if(this!=&mat) // 不能复制自己 { delete [] element; // 将原来的element删除 row = mat.row; col = mat.col; element = new T [row*col]; // 复制元素 for(int i=0; i<(row*col); i++) { element[i] = mat.element[i]; } } return *this; } // 用()表示矩阵索引 template<typename T> T& matrix<T>::operator()(int i, int j) const { if(i>row || i<1 || j>col || j<1) { //throw invalid_argument("Matrix index out of bounds"); throw index_OutOf_Bound(i, j); } return element[col*(i-1)+(j-1)]; } template<typename T> matrix<T> matrix<T>::operator+() { return *this; } //定义矩阵加法 template<typename T> matrix<T> matrix<T>::operator+(const matrix<T>& mat) { // 先判断矩阵的维度 if(col!=mat.cols() || row!=mat.rows()) { //throw runtime_error("The matrix size mismatch"); throw size_mismatch_exception(row, col, mat.row, mat.col); // 矩阵维度不匹配 } matrix<T> w(row, col); // 定义一个新的矩阵 for(int i=0; i<row*col; i++) { w.element[i] = element[i] + mat.element[i]; } return w; } template<typename T> matrix<T> matrix<T>::operator-() { matrix<T> tmp(row, col); for(int i=0; i<row*col; i++) { tmp.element[i] = -element[i]; } return tmp; } // 定义矩阵减法 template<typename T> matrix<T> matrix<T>::operator-(const matrix<T>& mat) { if(col!=mat.cols() || row!=mat.rows()) { //throw runtime_error("The matrix size mismatch"); throw size_mismatch_exception(row, col, mat.row, mat.col); // 矩阵维度不匹配 } matrix<T> w(row, col); // 定义一个新的矩阵 for(int i=0; i<row*col; i++) { w.element[i] = element[i] - mat.element[i]; } return w; } template<typename T> matrix<T> matrix<T>::operator+=(const T num) { matrix<T> w(row, col); for(int i=0; i<row*col; i++) { w.element[i] = element[i] +num; } return w; } //定义矩阵乘法 template<typename T> matrix<T> matrix<T>::operator*(const matrix<T>& mat) const { // 先判断矩阵的维度 if(col!=mat.rows()) { // throw runtime_error("Matrix size mismatch"); throw size_mismatch_exception(row, col, mat.row, mat.col); } matrix<T> w(row, mat.col); for(int i=1; i<=row; i++) { for(int j=1; j<=mat.col; j++) { T sum = element[col*(i-1)+(1-1)] * mat(1, j); // 注意这里的处理方法 。先直接计算第一项,相当于给sum赋初值,因为这里的sum不能初始化为0 for(int k=2; k<=col; k++) // k从2开始 { sum += element[col*(i-1)+(k-1)] * mat(k, j); } w(i, j) = sum; } } return w; } template<typename T> void matrix<T>::print_matrix() const { for(int i=1; i<=row; i++) { for(int j=1; j<=col; j++) { cout << element[col*(i-1)+(j-1)] << " "; } cout << endl; } cout << endl; } template<typename T> matrix<T> matrix<T>::tranpose() const { matrix<T> tmp(col, row); // 存放转置后的矩阵 for(int i=1; i<=row; i++) { for(int j=1; j<=col; j++) { tmp(j,i) = element[col*(i-1)+(j-1)]; } } return tmp; } #endif
测试函数:
main.cpp
#include <iostream> #include "E:\back_up\code\c_plus_code\matrix\external_file\matrix.h" //#include <stdexcept> using namespace std; int main(int argc, char *argv[]) { // 矩阵乘法; matrix<int> m6(2,3); for(int i=1; i<=2; i++) { for(int j=1; j<=3; j++) { m6(i,j)= (i-1)*3+j; } } matrix<int> m7(2,2); for(int i=1; i<=2; i++) { for(int j=1; j<=2; j++) { m7(i,j) = (i-1)*2+j; } } m6.print_matrix(); m7.print_matrix(); matrix<int> m8; try // 添加异常捕获代码; { m8 = m6*m7; cout << "---测试 operator* ----" << endl; m8.print_matrix(); cout << "---测试 transpose ----" << endl; matrix<int> m9; m9 = m8.tranpose(); m9.print_matrix(); } catch(size_mismatch_exception& ex) { cout << "Exception: " << ex.what() << endl; ex.diaplay_error_detail(); } /*********测试indexException*************/ matrix<int> m1(2,3); for(int i=1; i<=2; i++) { for(int j=1; j<=3; j++) { m1(i,j)= (i-1)*3+j; } } m1.print_matrix(); try { int a = m1(1,2); int b = m1(2,4); cout << "result is " << (a+b) << endl; } catch(index_OutOf_Bound& ex) { cout << ex.what() << endl; ex.display_exception_info(); } return 0; }
测试结果:
------------------------------------------------------分割线----------------------------------------------------------
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)