数据结构——矩阵
来源:互联网 发布:sftp 批量下载 java 编辑:程序博客网 时间:2024/06/02 00:17
数据结构——矩阵
1.1矩阵类
1.定义
template<class T>class Matrix{private:int rows, cols; // 矩阵的行数和列数T *element; // 矩阵的元素public:Matrix(int r = 0, int c = 0); // 构造函数Matrix(const Matrix<T>& m); // 复制构造函数 ~Matrix() {delete [] element; } // 析构函数int Rows() const {return rows; } // 返回矩阵行数int Columns() const {return cols; } // 返回矩阵列数T & operator() (int i, int j) const; // 重载下标操作符Matrix<T>& operator = (const Matrix<T>& m); // 重载赋值运算符Matrix<T> operator +() const; // 重载一元加法运算符Matrix<T> operator +(const Matrix<T> & m) const; // 重载二元加法运算符Matrix<T> operator -() const; // 重载一元减法运算符Matrix<T> operator -(const Matrix<T> & m) const; // 重载二元减法运算符Matrix<T> operator *(const Matrix<T> & m) const; // 重载乘法运算符Matrix<T> operator +=(const T& x); // 重载增值运算符};
2.重载乘法运算符:(时间复杂性为O(rows*cols*m.cols) .)
template<class T>Matrix<T> Matrix<T>:: operator * ( const Matrix<T> & m) const {if ( cols != m.rows ) {cout << “Size not matched” <<endl; exit(1);}Matrix<T> w (rows, m.cols); // 创建一个临时矩阵,存放二矩阵相乘的结果int ct = 0, cm = 0, cw = 0; // 设定初始位置for ( int i =1 ; i <= rows; i++ ){for ( int j = 1 ; j <= m.cols ; j++ ){T sum = element[ct]*m.element[cm] ;for ( int k = 2 ; k <= cols ; k++ ){ ct++; // 指向*this第i行的下一个元素 cm += m.cols; // 指向m第j列的下一个元素 sum += element[ct] * m.element[cm]; } w.element[cw] = sum; // 保存计算得到的w(i,j)值 cw++; ct – = cols–1; // 重新指向本行的行首元素 cm = j; // 指向m第j+1列的列首元素}ct += cols; // 指向下一行的行首元素cm = 0; // 重新指向第一列的列首元素}return w; }
1.2特殊矩阵
1.对角矩阵的压缩存储
若n*n的方阵M是对角矩阵,则对所有的i≠j (0<i<n, 0<j<n) 都有M(i, j)=0,即非对角线上的元素均为0 .
对于一个nn维对角矩阵,至多只有n个非零元素,因此只需存储其n个对角元素的信息。
采用一维数组d[n]来压缩存储对角矩阵,其中d[i]存储M[i, i]的值。
2.三角矩阵的压缩存储(以下三角矩阵为例)
考虑一个n*n维下三角矩阵,其第一行有1个非零元素,第二行有2个非零元素,…,第n行有n个非零元素,非零元素共有(1+2+…+n) = n(n+1)/2个。可以用大小为n(n+1)/2的一维数组来存储下三角矩阵,即把下三角矩阵M的非零元素映射到一个一维数组d中。映射次序可采用按行优先或按列优先。
设元素M(i, j)前面有k个元素,可以计算出 k =1+2+…+ (i *1) + (j*1)= i(i*1)/2 + (j*1)。设一维数组d的下标是从0开始,则M(i, j)映射到d中所对应的元素是d[k] . 有了k的计算公式,可以很容易实现下三角矩阵的压缩存储。
3.对称矩阵的压缩存储
因为对称矩阵中M(i, j)与M(j, i)的信息相同,所以只需存储M的上三角部分或下三角部分的元素信息。
参照下三角矩阵的压缩存储方法,即用大小为n(n+1)/2的一维数组来存储,对于对称矩阵中的下三角矩阵元素M(i, j) (i*j) ,和下三角矩阵压缩存储的映射公式一样,映射到d[k] (其中k = i(i*1)/2 + (j*1) );对于对称矩阵中的上三角矩阵元素M(i, j) (i<j,不包含对角线上矩阵元素) ,因其元素值与下三角中的M(j, i)相同,故映射到d[q](其中q= j(j*1)/2 + (i*1)). 有了k和q的计算公式,即可实现对称矩阵的压缩存储。
4.稀疏矩阵的压缩存储
(1)定义:设矩阵中非零元素的个数远远小于零元素的个数,则称 A 为稀疏矩阵。
◆ 特点:零元素的分布一般没有规律。
◆ 作用:解决空间浪费的问题。
(2) 存储非零节点:由三个域(行号、列号和元素值)构成的结点被称为三元组结点:矩阵的每个非零元素可由一个三元组结点(i,j,aij)唯一确定。
(3)存储稀疏矩阵的方法:
a. 用顺序存储方式实现的三元组表(将表示稀疏矩阵的非零元素的三元组结点按行优先的顺序排列,得到一个线性表,将此线性表用顺序存储结构存储起来,称之为三元组表。)
b. 链接存储方式实现的十字链表。
(4)类声明
template <class T> // 三元组的结点类 class Trituple { firend class SparseMatrix; private: int row, col; // 非零元素的行号、列号 T value; // 非零元素的值 };template <class T> // 稀疏矩阵类的声明class SparseMatrix { private: // 稀疏矩阵的行数、列数及非零元素个数 int Rows, Cols, Count; // 存储三元组表的数组 int MaxTerm; Trituple <T> smArray[MaxTerm]; public: // 建立一个稀疏矩阵 SparseMatrix( int Mrows,int Mcols); // 求转置矩阵 SparseMatrix <T> Transpose( ); // 求矩阵的和 SparseMatrix <T> Add(SparseMatrix <T> b); // 求矩阵的乘积 SparseMatrix <T> Multiply(SparseMatrix <T> b);};
(5)类实现
template <class T> // 求转置矩阵 SparseMatrix <T>SparseMatrix::Transpose( ) { SparseMatrix <T> b; // 声明一个稀疏矩阵b b.Rows = Cols; // b的行数等于原矩阵的列数 b.Cols = Rows; // b的列数等于原矩阵的行数 b.Count = Count; // b与原矩阵的非零元素个数相同 if ( Count > 0 ) // 若有非零元素{ int Bnubmer = 0; for(k=0;k<Cols;k++) for(i=0;i<Count;i++) if(smArray[i].col==k) { b.smArray[Bnumber].row=k; b.smArray[Bnumber].col= smArray[i].row; b.smArray[Bnumber].value= smArray[i].value; Bnumber++;} } return b; // 返回转置矩阵 b }
可知:;循环次数为A′(A的转置矩阵)的行数n,执行次数是矩阵非零元素个数t,显然,求转置矩阵的时间复杂性为O(nt) .
(6)十字链表
矩阵的元素结构如下:分别表示该元素的左邻非零元素、上邻非零元素、所在的行、所在的列和它的值。
矩阵的每一行、每一列都设置为由一个表头结点引导的循环链表,并且各行和各列的表头结点有如下特点:
-1 = COL(Loc(BASEROW[i]))< 0
-1 = ROW(Loc(BASECOL[j]))< 0
十字链表为:
若某一行没有非零元素,则 LEFT(BASEROW[i])=BASEROW[i]
若某一列没有非零元素,则 UP(BASECOL[i])=BASECOL[i]
综上可知: 对矩阵的运算实质上就是在十字链表中插入结点、删除结点以及改变某个结点的 VAL 域的值。
实现算法:
//ADL语言实现算法算法 SP(BASE,PIVOT)// 稀疏矩阵的主步骤操作,稀疏矩阵的表示方式为正交链表,指针变量PIVOT// 指向主元素,一维数组PTR[1:n]是指针型SP1 [初始化,确定主行I0,主列J0 ] I0←ROW(PIVOT) . J0←COL(PIVOT) . α←1.0 / VAL(PIVOT) . VAL(PIVOT) ←1.0 . P0←Loc(BASEROW[I0]) . Q0←Loc (BASECOL[J0]) .SP2 [处理主行I0] P0←LEFT(P0) . J←COL(P0) . IF J<0 THEN GOTO SP3. ELSE (PTR[J] ←Loc(BASECOL[J]) . VAL(P0) ←α* VAL(P0) . GOTO SP2. ) .SP3 [找新行I,并指定P1] Q0←UP(Q0) . I←ROW (Q0) . IF I<0 THEN RETURN . IF I=I0 THEN GOTO SP3 . P←Loc(BASEROW[I]) . P1←LEFT(P) .SP4 [确定新列J] P0←LEFT(P0) . J←COL(P0) . IF J<0 THEN (VAL(Q0)← -α* VAL(Q0) . GOTO SP3. ) . IF J=J0 THEN GOTO SP4 .SP5 [P1所指元素所在的列与J列比较] WHILE COL(P1) > J DO (P←P1 . P1←LEFT(P)) . IF COL(P1) =J THEN GOTO SP7 .SP6 [插入新元素] WHILE ROW(UP(PTR[J])) > I DO PTR[J]←UP(PTR[J]) . X<=AVAIL . VAL(X) VAL(Q0)VAL(P0) . ROW(X) ←I . COL(X) ←J . LEFT(X) ← P1 . UP(X) ←UP(PTR[J]) . LEFT(P) X . P X. UP(PTR[J]) X . PTR[J] X . GOTO SP4.SP7 [主步骤操作] VAL(P1) ←VAL(P1) - VAL(Q0)* VAL(P0) . IF VAL(P1)=0 THEN GOTO SP8 . ELSE (PTR[J]←P1 . P←P1 . P1←LEFT(P) . GOTO SP4 . ) . SP8 [删除零元素] WHILE UP(PTR[J]) ≠ P1 DO PTR[J]←UP(PTR[J]) . UP(PTR[J])←UP(P1) . LEFT(P)←LEFT(P1) . AVAIL <= P1 . P1 ←LEFT(P) . GOTO SP4. ▐
- 数据结构——矩阵
- R数据结构—矩阵
- 数据结构——稀疏矩阵
- 稀疏矩阵——数据结构
- 数据结构实验十——对称矩阵
- 数据结构实验10——稀疏矩阵
- 数据结构实践——稀疏矩阵相加
- 数据结构之——稀疏矩阵
- 数据结构——矩阵查找(牛客网1)
- 数据结构——矩阵及其常用操作
- 数据结构——数组—稀疏矩阵及运算
- 数据结构——稀疏矩阵的压缩存储
- 《学习opencv》笔记——基本数据结构,CvMat,矩阵访问
- 数据结构实践——稀疏矩阵的三元组表示
- 数据结构学习笔记——数组与矩阵压缩
- 数据结构与算法——求最大子矩阵问题
- 数据结构——特殊矩阵的压缩存储
- C语言数据结构——矩阵的加减乘除
- ORACLE中SID和SERVICE_NAME的区别
- Linux -- 进程间通信几种方式的总结
- Kotlin-解构声明
- iptables深入解析:mangle篇
- AngularJS(一)_表达式{{}}
- 数据结构——矩阵
- Java中的反射(四)总结一下
- ubuntu跑起IDEA的全套教程
- eclipse导入远程git代码及(push、pull、及maven工程导入)
- 初识Apache Hadoop
- JMeter学习-003-JMeter与LoadRunner的异曲同工
- iOS 中 AFNetworking HTTPS 的使用
- 实现JSP分页方法一:手写
- Java URL处理