数据结构预算法(六) 数组和矩阵(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;
}
测试结果:
------------------------------------------------------分割线----------------------------------------------------------