数组与矩阵

数组和矩阵

在实际应用中,数据通常以表的形式出现。尽管用数组来描述表是最自然的方式,但为了减少程序所需的时间和空间,经常采用自定义的描述方式。例如,当表中大部分元素都为0的时候,就会采用自定义的描述方式。
一个数组的每一个实例都是形如**(索引,值)**的数对集合,其中任意两个数对的值都不相同。有关数组的操作如下:

  1. 取值——给定一个索引,取对应数对中的值
  2. 存值——把一个新数对加到数对集合中。如果已经存在一个索引相同的数对,就用新数对覆盖。

数组的存取分为行主映射和列主映射
值得注意的是,二维数组int x[3][5]和int x[15]占用空间是不一样的,x[3][5]占用的空间是sizeof(int)*(3*5+3)=72,x[15]占用的空间是sizeof(int)*(15)=60,因为二维数组x[3][5]实际上是创建了一个长度为3的一维数组x,x的每一个元素是一个长度为5的一维数组。长度为3的一维数组存储的是第二维的指针。所以要多出来一些存储空间。

不规则二维数组

#include <iostream>
using namespace std;

int main(void)
{
	int numberOfRows = 5;
	//定义每一行的长度
	int length[5]={6,3,4,2,7};
	
	//声明一个二维数组变量
	//且分配所需要的行数
	int **irregularArray = new int* [numberOfRows];
	//分配每一行空间
	for(int i = 0; i < numberOfRows;i++)
		irregularArray[i] = new int [length[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;
}

矩阵

矩阵需要注意的就是矩阵乘法,其中m×n的矩阵A和q×p的矩阵B相乘,只有在n=q时才能进行乘法运算,结果是一个m×p的矩阵。
注意的是,因为是一维数组方式存储的,所以在矩阵(i,j)位置的元素实际上再数组的(i-1)*theRows+j的位置上,所以在矩阵乘法时要注意相乘位的表示。

#ifndef MATRIX_H_INCLUDED
#define MATRIX_H_INCLUDED
#include<iostream>
#include"myException.h"
using namespace std;

template<class T>
class matrix
{
    friend ostream& operator<<(ostream&, const matrix<T>&);
public:
    matrix(int theRows = 0,int 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
};

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 * theColumns];

    //复制m的每一个元素
    copy(m.element,
         m.element + theRows * theColumns,
         element);
}

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;
}

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
{// Return (*this) - m.
   if (theRows != m.theRows
       || theColumns != m.theColumns)
      throw matrixSizeMismatch();

   // create result matrix w
   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
{// Return w = -(*this).

   // create result matrix w
   matrix<T> w(theRows, theColumns);
   for (int i = 0; i < theRows * theColumns; i++)
      w.element[i] = -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 matrixSizeMismatch();

    matrix<T> w(theRows,m.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行
        //ct在行方向移动,所以是++,而cm在列方向移动,所以是+m.theColumns
        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;
}


template<class T>
matrix<T>& matrix<T>::operator+=(const T& x)
{// Increment all elements of *this by x.
   for (int i = 0; i < theRows * theColumns; i++)
       element[i] += x;
   return *this;
}

template<class T>
ostream& operator<<(ostream& out, const matrix<T>& m)
{// Put matrix m into the stream out.
 // One row per line.
   int k = 0;  // index into element array
   for (int i = 0; i < m.theRows; i++)
   {// do row i
      for (int j = 0; j < m.theColumns; j++)
         out << m.element[k++] << "  ";

      // row i finished
      out << endl;
   }

   return out;
}

// for some reason compiler can't create this on its own
ostream& operator<<(ostream& out, const matrix<int>& m)
{// Put matrix m into the stream out.
 // One row per line.
   int k = 0;  // index into element array
   for (int i = 0; i < m.theRows; i++)
   {// do row i
      for (int j = 0; j < m.theColumns; j++)
         out << m.element[k++] << "  ";

      // row i finished
      out << endl;
   }

   return out;
}
#endif // MATRIX_H_INCLUDED

特殊矩阵

方阵是行数和列数相同的矩阵。一些常用的特殊方阵如下:
对角矩阵:当且仅当i≠j时,M(i,j) = 0;
三对角矩阵:当且仅当|i-j|>1时,M(i,j) = 0;
下三角矩阵:当且仅当i<j时,M(i,j)=0;,三角矩阵共有n(n+1)/2个元素。
上三角矩阵:当且仅当i>j时,M(i,j)=0;
对称矩阵:当且仅当对于所有的i和j,M(i,j)=M(j,i)。
注意各个对应元素与element一维数组的对应关系即可。

稀疏矩阵

一个m×n的矩阵,如果大多数元素都是0,则称为稀疏矩阵,一个矩阵如果不是稀疏的,就称为稠密矩阵,在稀疏矩阵和稠密矩阵之间没有明确界限。
稀疏矩阵可以考虑用单个线性表来描述,
在这里插入图片描述
稀疏矩阵比较重要的是转置的实现
实现如下:创建两个数组colSize和rowNext,colSize[i]是输入矩阵*this在第i列的非0元素个数,rowNext[i]是转置矩阵第i行首个非0元素在b中的索引。例如,对于上图的稀疏矩阵,colSize[1:8]=[0,2,1,2,1,1,1,1]。rowNext=[0,0,2,3,5,6,7,8]。
流程为计算colSize[1:8]->计算rowNext[1:8],
rowNext[1] = 0;
rowNext[i] = rowNext[i-1]+colSize[i-1];
稀疏矩阵的每个元素是terms的结构数组。

// a term in sparseMatrix

#ifndef matrixTerm_
#define matrixTerm_

using namespace std;

template <class T>
struct matrixTerm
{
   int row,
       col;
   T value;

   operator T() const {return value;}
      // type conversion from matrixTerm to T
};

#endif

稀疏矩阵类如下

// sparse matrix using an extended array list

#ifndef sparseMatrix_
#define sparseMatrix_

#include <iostream>
#include "matrixTerm.h"
#include "extendedArrayList.h"
#include "myException.h"

template<class T>
class sparseMatrix
{
   friend ostream& operator<<
          (ostream&, sparseMatrix<T>&);
   friend istream& operator>>
          (istream&, sparseMatrix<T>&);
   public:
      void transpose(sparseMatrix<T> &b);
      void add(sparseMatrix<T> &b, sparseMatrix<T> &c);
   private:
      int rows,    // number of rows in matrix
          cols;    // number of columns in matrix
      arrayList<matrixTerm<T> > terms;
                   // list of nonzero terms
};

// overload <<
//template <typename T>
template <class T>
ostream& operator<<(ostream& out, sparseMatrix<T>& x)
{// Put x in output stream.

   // put matrix characteristics
   out << "rows = " << x.rows << " columns = "
       << x.cols  << endl;
   out << "nonzero terms = " << x.terms.size() << endl;

   // put terms, one per line

   for (typename arrayList<matrixTerm<T> >::iterator i = x.terms.begin();i != x.terms.end(); i++)
      out << "a(" << (*i).row << ',' << (*i).col
          << ") = " << (*i).value << endl;

   return out;
}

// overload >>
template<class T>
istream& operator>>(istream& in, sparseMatrix<T>& x)
{// Input a sparse matrix.

   // input matrix characteristics
   int numberOfTerms;
   cout << "Enter number of rows, columns, and #terms"
        << endl;
   in >> x.rows >> x.cols >> numberOfTerms;

   // set size of x.terms and ensure enough capacity
   x.terms.reSet(numberOfTerms);

   // input terms
   matrixTerm<T> mTerm;
   for (int i = 0; i < numberOfTerms; i++)
   {
      cout << "Enter row, column, and value of term "
           << (i + 1) << endl;
      in >> mTerm.row >> mTerm.col >> mTerm.value;
      x.terms.set(i, mTerm);
   }

   return in;
}


/****************************************************************/
// explict code tooverload with T = int for test as compiler
// unable to generate

// overload <<
ostream& operator<<(ostream& out, sparseMatrix<int>& x)
{// Put x in output stream.

   // put matrix characteristics
   out << "rows = " << x.rows << " columns = "
       << x.cols  << endl;
   out << "nonzero terms = " << x.terms.size() << endl;

   // put terms, one per line
   for (arrayList<matrixTerm<int> >::iterator i = x.terms.begin();
        i != x.terms.end(); i++)
      out << "a(" << (*i).row << ',' << (*i).col
          << ") = " << (*i).value << endl;

   return out;
}

// overload >>
istream& operator>>(istream& in, sparseMatrix<int>& x)
{// Input a sparse matrix.

   // input matrix characteristics
   int numberOfTerms;
   cout << "Enter number of rows, columns, and #terms"
        << endl;
   in >> x.rows >> x.cols >> numberOfTerms;

   // set size of x.terms and ensure enough capacity
   x.terms.reSet(numberOfTerms);

   // input terms
   matrixTerm<int> mTerm;
   for (int i = 0; i < numberOfTerms; i++)
   {
      cout << "Enter row, column, and value of term "
           << (i + 1) << endl;
      in >> mTerm.row >> mTerm.col >> mTerm.value;
      x.terms.set(i, mTerm);
   }

   return in;
}
/****************************************************************/
template<class T>
void sparseMatrix<T>::transpose(sparseMatrix<T> &b)
{// Return transpose of *this in b.

   // set transpose characteristics
   b.cols = rows;
   b.rows = cols;
   b.terms.reSet(terms.size());

   // initialize to compute transpose
   int* colSize = new int[cols + 1];
   int* rowNext = new int[cols + 1];

   // find number of entries in each column of *this
   for (int i = 1; i <= cols; i++) // initialize
      colSize[i] = 0;
   for (typename arrayList<matrixTerm<T> >::iterator i = terms.begin();
        i != terms.end(); i++)
      colSize[(*i).col]++;

   // find the starting point of each row of b
   rowNext[1] = 0;
   for (int i = 2; i <= cols; i++)
      rowNext[i] = rowNext[i - 1] + colSize[i - 1];

   // perform the transpose copying from *this to b
   matrixTerm<T> mTerm;
   for (typename arrayList<matrixTerm<T> >::iterator i = terms.begin();
        i != terms.end(); i++)
   {
      int j = rowNext[(*i).col]++; // position in 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)
{// Compute c = (*this) + b.

   // verify compatibility
   if (rows != b.rows || cols != b.cols)
     throw matrixSizeMismatch(); // incompatible matrices

   // set characteristics of result c
   c.rows = rows;
   c.cols = cols;
   c.terms.clear();
   int cSize = 0;

   // define iterators for *this and b
   typename arrayList<matrixTerm<T> >::iterator it = terms.begin();
   typename arrayList<matrixTerm<T> >::iterator ib = b.terms.begin();
   typename arrayList<matrixTerm<T> >::iterator itEnd = terms.end();
   typename arrayList<matrixTerm<T> >::iterator ibEnd = b.terms.end();

   // move through *this and b adding like terms
   while (it != itEnd && ib != ibEnd)
   {
     // row-major index plus cols of each term
     int tIndex = (*it).row * cols + (*it).col;
     int bIndex = (*ib).row * cols + (*ib).col;

     if (tIndex < bIndex)
     {// b term comes later
   	 c.terms.insert(cSize++, *it);
         it++;
     }
     else {if (tIndex == bIndex)
           {// both in same position

              // append to c only if sum not zero
              if ((*it).value + (*ib).value != 0)
              {
                 matrixTerm<T> mTerm;
                 mTerm.row = (*it).row;
                 mTerm.col = (*it).col;
                 mTerm.value = (*it).value + (*ib).value;
                 c.terms.insert(cSize++, mTerm);
              }

              it++;
              ib++;
           }
           else
           {// a term comes later
              c.terms.insert(cSize++, *ib);
              ib++;
           }
          }
     }

   // copy over remaining terms
   for (; it != itEnd; it++)
      c.terms.insert(cSize++, *it);
   for (; ib != ibEnd; ib++)
      c.terms.insert(cSize++, *ib);
}

#endif

刚开一直没运行成功,一直出现这个错误
need typename before because is a dependent scope,通过百度搜索,在每个iterator前加了typename关键字,问题得到解决,首先看一下template<class T>和template<typename T>的区别
总而言之:typename的作用就是告诉c++编译器,typename后面的字符串为一个类型名称,而不是成员函数或者成员变量,这个时候如果前面没有typename,编译器没有任何办法知道arrayList<matrixTerm<T>>::iterator是一个类型还是一个成员名称(静态数据成员或者静态函数),所以编译不能够通过。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值