数组和矩阵

64 篇文章 0 订阅

数组

  • 在图7-1中,从第一行开始,依次对每一行的索引从左至右连续编号,得到图7-2a所示的映射结果。它把二维数组的索引映射为[0,n-1]中的数,这种映射方式称为行主映射( row major mapping)。索引对应的数称为行主次序( row-major order)。
  • 图7-2b是另一种映射模式,称为列主映射图7-1 整型数组score [3] [6]的索引排列表( column major mapping)。
  • 在列主映射中,对索引的编号从最左列开始,依次对每一列的索引从上到下连续编号。
  • 在行主次序中,映射函数为: map(i1,i2)= i1*U2+ i2,其中u2是数组的列数。
    在这里插入图片描述
  • 将多维数组映射为一维数的时候,采用行主映射公式。
  • 三维数组的行主映射函数为: map(i1,i2,i3) = i1u2u3 + i2*u3 + i3
  • C++用所谓数组的数组来表示一个多维数组。一个二维数组被表示为一个一维数组,这个一维数组的每一个元素还是一个一维数组。
  • 一个三维数组被表示为一个一维数组,这个一维数组的每一个元素是一个二维数组。

一个不规则二维数组的创建和使用

int main (void)
{
	int numberOfRows = 5;
	//1定义每一行的长度
	int length[5] = (634, 27};
	//声明一个二维数组变量
	//且分配所需要的行数
	int **irregularArray = new int* [numberOfRows] ;
	//分配每一行的空间
	for (int i = 0; i < numberOfRows; i++)
	{
		irregularArray[i] = new int [1ength[i]];
	}
	//像使用规则数组一样使用不规则数组.
	irregularArray[2][3] = 5;
	irregularArray[4][6] = irregularArray[2][3] + 2;
	irregularArray[1][1] = 3;
	//输出选择的数组元素
	cout << irregularArray[2][3] << endl ;
	cout << irregularArray[4][6] << endl;
	cout << irregularArray[1][1] << endl;
	return 0}

矩阵

  • 计算过程中,将二维数组转换为一维数组,利用行主映射公式。

矩阵类matrix的声明

template<class T>
class matrix
[
	friend ostream& operator<< (ostream&, const matrix<T>&) ;
public:
	matrix(int theRows = 0int theColumns = 0) ;
	matrix(const matrix<T>&) ;
	~matrix() {delete [] element; }
	int rows() const { return theRows; }
	int columns() const { return theColumns; }
	T& operator () (int i, int j) const;
	matrix<T>& operator= (const matrix<T>&) ;
	matrix<T> operator+ () const;
	matrix<T> operator+ (const matrix<T>&) const;
	matrix<T> operator- () const;
	matrix<T> operator- (const matrix<T>&) const;
	matrix<T> operator* (const matrix<T>&) const; 
	matrix<T>& operator+= (const T&) ;
private:
	int theRows, //矩阵的行数
	theColumns;  //矩阵的列数
	T *element;  //数组element
};

矩阵类 matrix的构造函数和复制构造函数

template<class T>
matrix<T>::matrix (int theRows, int theColumns)
{
	//矩阵构造函数
	//检验行数和列数的有效性
	if (theRows < 0 || theColumns < 0)
		throw illegalParameterValue("Rows and columns must be >= 0") ;
	if ( (theRows == 0 || theColumns == 0)&&(theRows != 0 || theColumns != 0))
		throw illegalParameterValue("Either both or neither rows and columns should be zero") ;
	//创建矩阵
	this->theRows = theRows ;
	this->theColumns = theColumns;
	element = new T [theRows * theColumns] ;
}

template<class T>
matrix<T>::matrix (const matrix<T>& m)
{
	//矩阵的复制构造函数
	//创建矩阵
	theRows = m. theRows ; .
	theColumns = m. theColumns;
	element = new T [theRows * theCol umns] ;
	//复制m的每一个元素
	copy (m.element, m.element + theRows * theColumns, element) ;
}

矩阵类matrix对赋值操作符=的重载

template<class T>
matrix<T>& matrix<T>::operator= (const matrix<T>& m)
{
	//赋值。(*this) = m
	if (this != &m)
	{
		//不能自己复制自己
		delete [] element;
		theRows = m. theRows;
		theColumns = m. theColumns;
		element = new T [ theRows * theColumns] ;
		//复制每一个元素
		copy(m. element, m.element + theRows * theColumns, element) ;
	}
	return *this;
}

矩阵类 matrix对()操作符的重载

template<class T>
T& matrix<T>::operator() (int i, int j) const
{
	//返回对元素element (i,j) 的引用
	if(i<1 || i>theRows || j<1 || j > theColumns)
		throw matrixIndexOutOfBounds () ;
	return element[(i一1) * theColumns + j - 1] ;
}

矩阵加法

template<class T>
matrix<T> matrix<T>::operator+ (const matrix<T>& m) const
{
	//返回矩阵w = (*this) + m
	if (theRows != m.theRows || theColumns != m.theColumns)
		throw matrixSizeMismatch() ;
		
	//生成结果矩阵
	matrix<T> w (theRows, theColumns) ;
	for (int i = 0; i < theRows * theColumns; i++)
		w.element[i] = element[i] + m.element[i] ;
	return w;
}

矩阵乘法

template<class T>
matrix<T> matrix<T>: :operator* (const matrix<T>& m) const
{
	//矩阵乘法.返回结果矩阵 w = (*this) * m
	if (theColumns != m. theRows) 
		throw matrixSi zeMismatch() ;
	matrix<T> w (theRows,theColumns) ;
	//定义矩阵*this, m和w的游标且初始化以为(1,1)元素定位
	int ct=0,cm=0,cw=0;
	//对所有i和j计算w(i,j)
	for (int i = 1; i <= theRows; i++)
	{//计算结果矩阵的第i行
		for (int j = 1; j <= m.theColumns; j++)
		{ 
		//计算w(i,j)第一项
			T sum = element[ct] * m. element [cm] ;
			//累加其余所有项
			for (int k = 2; k <= theColumns; k++)
			{
				ct++;
				cm += m.theColumns;
				sum += element [ct] * m.element [cm] ;
			}
			w.element [cw++] = sum;
			//从行的起点和下一列从新开始
			ct -= theColumns - 1 ;
			cm=j;
		}
		//从下一行和第一列重新开始
		ct += theColumns;
		cm=0;
	}
	return w;
}

特殊矩阵

对角矩阵( diagonal)。M是一个对角矩阵,当且仅当 i≠j 时,M(i,j)=0。

  • element [i-1] [j-1] 表示D(i,j)。这种表示法需要rows^2 个类型为T的数据空间。然而,对角矩阵最多只有rows个非0元素,因此可以用一维数组clement[rows]来表示对角矩阵,其中element[i-1]表示D(i,i)。所有未在一维数组中出现的矩阵元素均为0。
三对角矩阵( tridiagonal)。M是一个三对角矩阵,当且仅当|i-j| >1 时,M(i,j) =0。
  • 在一个rows * rows的三对角矩阵中,非0元素排列在如下三条对角线上:
    1)主对角线: i=j。
    2)主对角线之下的对角线( 称低对角线):i=j+1。
    3)主对角线之上的对角线(称高对角线):i=j-1。
  • 这三条对角线上的元素总数为3 * rows-2。可以用一个容量为3*rows-2的一维数组element来描述三对角矩阵,因为只有三条对角线上的元素需要真正地存储。
  • 逐行映射。
  • 如果逐列映射。
  • 逐条对角线映射。
下三角矩阵( lower triangular )。M是个下三角矩阵,当且仅当i<j时,M(i,j)=0。上三角矩阵( upper triangular)。M是一个上三角矩阵,当且仅当j时,M(i,j)=0。
  • 这两种三角矩阵都可以用一个大小为 n(n+1)/2 的一维数组来表示。
  • 元素L(i, j)在数组element中的位置:i(i-1)/2+j-1。
对称矩阵(symmetric)。M是一个对称矩阵,当且仅当对于所有的i和j,M(i,j)=M(j,i)。
  • 由于对称性,只需存储一半的数据即可,用一个大小为n(n+1)/2的一维数组来表示。

稀疏矩阵

类spareMatrix的头

template<class T>
class sparseMatrix
{
	public:
		void transpose(sparseMatrix<T> &b) ;//转置矩阵
		void add(sparseMatrix<T> &b, sparseMatrix<T> &C) ;
	private :
		int rows, //矩阵行数
		cols; //矩阵列数
		arrayList<matrixTerm<T> > terms; //非0项表
};

稀疏矩阵的转置

template<class T>
void sparseMatrix<T>::transpose(sparseMatrix<T> &b)//b为传出参数
{
	//返回b中*this的转置
	//设置转置矩阵特征
	b.cols = rows;
	b.rows = cols;
	b.terms.reSet(terms.size()) ;
	
	//先将矩阵中的非0元素按行主映射到arrayLIst中
	//初始化以实现转置
	int* colSize = new int[cols + 1] ;
	int* rowNext = new int[cols + 1] ;
	
	//寻找*this 中每一列的项的数目
	for(int i=.1;i<=cols;i++)  //初始化
		colSize[i] = 0;
	for (arrayList<matrixTerm<T> >:: iterator i = terms.begin() ;i != terms.end() ; i++)
		colSize[(*i).col]++;
	//寻找b中每一行的起始点
	rowNext[1] = 0;
	for(int i=2;i<=cols;i++)
		rowNext[i] = rowNext[i - 1] + colSize[i-1];
	//实施从*this到b的转置复制
	matrixTerm<T> mTerm;
	for (arrayList <matrixTerm<T> >:: iterator i = terms.begin() ;i != terms.end() ; i++)
	{
		int j = rowNext[ (*i) .co1]++;  //b中的位置
		mTerm.row = (*i) .col;
		mTerm.col = (*i) . row;
		mTerm.value = (*i) . value;
		b.terms .set(j, mTerm) ;
	}
}

两个稀疏矩阵相加

template<class T>
void sparseMatrix<T>::add(sparseMatrix<T> &b,sparseMatrix<T> &c)
{
	//b为传入参数,c为传出参数
	//计算c=(*this)+b.
	//检验相容性
	if (rows != b.rows || cols != b.cols)
		throw matrixSizeMismatch() ;
	//矩阵不相容
	//设置结果矩阵c的特征
	c.rows = rows;
	c.cols = cols;
	c.terms.clear() ;
	int cSize = 0;
	//定义*this和b的迭代器
	arrayList<matrixTerm<T> >::iterator it = terms.begin() ;
	arrayList<matrixTerm<T> >::iterator ib = b.terms.begin() ;
	arrayList<matrixTerm<T> >::iterator itEnd = terms.end() ;
	arrayList<matrixTerm<T> >::iterator ibEnd = b.terms.end() ;
	
	//遍历*this和b,把相关的项相加
	while (it != itEnd && ib != ibEnd)
	{
		//行主索引加上每一项的列数
		//行*列数+列,先将矩阵转为一维矩阵
		int tIndex = (*it) .row * cols + (*it) .col;
		int bIndex = (*ib) .row * cols + (*ib) .col;
		
		if (tIndex < bIndex)
		{//b项在后
			//再插入一维矩阵中
			c. terms. insert (cSize++*it) ;
			it++;
		else {if (tIndex == bIndex)
		{//两项同在一个位置
			//仅当相加后不为0时加入c
			if ((*it) .value + (*ib) .value != 0)
			{
				matrixTerm<T> mTe rm;
				mTerm. row = (*it) . row;
				mTerm.col = (*it) .col;
				mTerm.value = (*it) .value + (*ib) . value;
				c. terms.insert(cSize++,mTerm) ;
			}
			it++;
			ib++;
		}
		else
		{//一项在后
			c.terms.insert(cSize++*ib) ;
			ib++; .
		}
	}
}

//复制剩余项,有一个到达end,而另一个没有到达end时
for (; it != itEnd; it++)
	c. terms. insert(cSize++*it) ;
for (; ib != ibEnd; ib++)
	c. terms. insert(cSize++, *ib) ;
}

用多个线性表描述矩阵

  • 把每行的非0元素串接在一起,构成一个链表,称作行链表(row chain )。
    在这里插入图片描述
  • 关于转置操作,我们使用箱子从输入矩阵*this中收集那些在结果矩阵中位于同一行的非0元素。bin[i] 是与结果矩阵b的第i行非0元素所对应的链表。

稀疏矩阵的转置

template<class T>
void linkedMatrix<T>:: transpose(linkedMatrix<T> &b)
{
	//将*this 的转置在矩阵b中返回
	b.headerChain.clear() ; //从b中删除所有节点
	//创建bins作为每行的头节点链表,以收集b的行
	extendedChain<rowElement<T> > *bin;
	bin = new extendedChain<rowElement<T> > [cols + 1];
	//头节点迭代器
	extendedChain<headerElement<T> >::iterator ih = headerChain.begin(),ihEnd = headerChain.end() ;
	//把*this 的项复制到bins
	while (ih != ihEnd)
	{//检查所有行
		int r = ih->row;
	//行链表的行数
	//行链表迭代器
		extendedChain<rowEl ement<T> > :: iterator ir = ih->rowChain.begin(),irEnd = ih->rowChain.end() ;
	
		//定义每行中元素的节点
		rowElement<T> x;
	//将*this 中行r中的项复制到b中的列r
		x.col = r;
		while (ir != irEnd)
		{//把行链表的一项复制到bin
			x.value = ir->value; .
			//x最终在转置矩阵的行ir->col 中.
			bin[ir->co1] .push_back(x) ;
			ir++; //行中的下一项
		}
		ih++; //进入下一行
	}
	//设置转置矩阵的维数
	b.rows = cols;
	b.cols = rows;
	//收集转置矩阵的头链表
	headerElement<T> h;
	//扫描bins
	for(inti=1;i<=cols;i++)
		if (!bin[i] . empty())
		{//转置矩阵的行i
			h.row = i;
			h. rowChain = bin[i] ;
			b.headerChain.push back(h) ;
			bin[i] .zero(); // 免于析构
		}
	h.rowChain. zero() ;
	//免于析构
	delete [] bin; 
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值