550 likes | 648 Views
Chapter 4. ARRAYS AND MATRICES. 4.1 ARRAYS. 数组是一种常用(熟悉)的数据结构。 线性表包括:数组和广义表。 4.4.1 The Abstract Data Type Each instance of the data object array is a set of pairs of the form (index, value). Example High = { (0,82), (1,79), (2,85), (3,92), (4,88), (5, 89), (6,91) }
E N D
Chapter 4 ARRAYS AND MATRICES
4.1 ARRAYS • 数组是一种常用(熟悉)的数据结构。 • 线性表包括:数组和广义表。 4.4.1 The Abstract Data Type • Each instance of the data object array is a set of pairs of the form (index, value). Example High = { (0,82), (1,79), (2,85), (3,92), (4,88), (5, 89), (6,91) } • The functions performed: • Create – Creates an initially empty array • Store – Adds a pair of the form to the set. • Retrieve – Retrieves the value of the pair that has a given index.
AbstractDataType Array { instances set of (index, value) pairs, no two pairs have the same index operations Create ( ): create an empty array Store (index,value ): add this pair to set deleting existing pair (if any) with the same index Retrieve (index ): return the pair with this index value } ADT 4.1 Abstract data type specification of an array
4.1.2 Indexing a C++ Array • The index (also called subscript) of an array in C++ must be of the form [i1][i2][i3] … [ik] int score [u1][u2][u3] … [uk] • (数组需要预留空间)The memory begins at byte start and extends up to and including byte start+size(score)-1
4.1.3 Row- and Column-Major Mappings • 数组的存储方式 • row major mapping (按行排列) • column major mapping (按列排列) • 访问元素位置: Start+map( i1,i2, i3, … ik )*sizeof(int)
[0][0] [0][1] [0][2] [0][3] [0][4] [0][5] [1][0] [1][1] [1][2] [1][3] [1][4] [1][5] [2][0] [2][1] [2][2] [2][3] [2][4] [2][5] Figure 4.1 Tabular arrangement of indices for int score[3][6] 0 1 2 3 4 5 0 3 6 9 12 15 6 7 8 9 10 11 1 4 7 10 13 16 12 13 14 15 16 17 2 5 8 11 14 17 • Row-major mapping (b) Column-major mapping Figure 4.2 Mapping a two-dimensional array
4.1.4 the Class Array1D • 一维数组可以看成是一个线性表或向量,适合于随机查找。 • Although C++ support one dimensional arrays,this support is rather primitive. • Ex.: To declared an array int a[ 9 ] Accessing a[-3], a[90] are invalid indexes. • the array cannot be output using the statement cout << a << endl;
template <class T> class Array1D { public : Array1D(int size = 0); Array1D(const Array1D<T>& v); //copy constructor ~Array1D( ) { delete [ ] element; } T& operator [ ](int i) const ; int Size( ) { return size; } Array1D<T>&operator = (const Array1D<T>&v); Array1D<T> operator + ( ) const; // unary + Array1D<T>operator + (const Array1D<T>& v) const; Array1D<T>operator - ( ) const; // unary minus Array1D<T>operator - (const Array1D<T>& v) const; Array1D<T>operator * (const Array1D<T>& v) const; Array1D<T>&operator += (const T& x); private: int size; T *element; // 1D array }; Program 4.1 A one-dimensional array class
template <class T> Array1D<T>::Array1D(int sz) { // Constructor for one-dimensional arrays. if (sz < 0) throw BadInitializers(); size = sz; element = new T[sz]; } template <class T> Array1D<T>::Array1D(const Array1D<T>& v) { // Copy constructor for one-dimensional arrays. size = v.size; element = new T[size]; // get space for (int i = 0; i < size; i++) // copy elements element[i] = v.element[i]; } Program 4.2 Constructors for a one-dimensional array
template <class T> T& Array1D<T>: :operator [ ] (int i) const { // Return reference to element i. if (i < 0 || i >= size) throw OutOfBounds( ); return element[i]; } Program 4.3 Overloading the array indexing operator template <class T> Array1D<T>& Array1D<T>: :operator = (const Array1D<T>& v) { // Overload assignment operator . if (this != &v) { // not self-assignment size = v.size; delete [ ] element; // free old space element = new T[size]; // get right amount for(int i = 0; i<size; i++) //copy elements element[i] = v.element[i]; } return *this ; } Program 4.4 Overloading the assignment operator
template <class T> Array1D<T> Array1D<T>::operator - (const Array1D<T>& v) const { if (size != v.size) throw SizeMismatch( ); Array1D<T> w(size); // Create result array w for (int i = 0; i < size; i++) w.element[i] = element[i] - v.element[i]; return w; } // return w=(*this)-v template <class T> Array1D<T> Array1D<T>::operator - ( ) const { Array1D<T> w(size); // Create result array w for (int i = 0; i < size; i++) w.element[i] = -element[i]; return w; } // return w=(*this)-v template <class T> Array1D<T>& Array1D<T> :: operator += (const T& x) { for (int i = 0; i < size; i++) element[i] += x; return *this ; } Program 4.5 Overloading binary minus, unary minus, and increment
4.1.5 The Class Array2D • A two-dimensional array is viewed as a collection of one-dimensional array. • 怎样将二维数组中元素存入到计算机内存中呢? • 数组一般不作插入或删除操作,一旦建立,则结构中的元素个数和相互间的关系就不再变动,即它们的逻辑结构不再发生变化。
template <class T> class Array2D { public: Array2D (int r = 0, int c = 0); Array2D(const Array2D<T>& m); ~Array2D( ) { delete [ ] row; } int Rows( ) const { return rows; } int Columns( ) const { return cols; } Array1D<T>& operator [](int i) const ; Array2D<T>& operator = (const Array2D<T>& m); Array2D<T> operator + ( ) const ; Array2D<T> operator + (const Array2D<T>& m) const ; Array2D<T> operator - ( ) const ; // unary minus Array2D<T> operator - (const Array2D<T>& m) const ; Array2D<T> operator * (const Array2D<T>& m) const ; Array2D<T>& operator += (const T& x); private: int rows, cols; Array1D<T> *row; }; Program 4.6 A class for two-dimensional arrays
template <class T> Array2D<T>::Array2D(int r, int c) { if (r < 0 || c < 0) throw BadInitializers( ); if ((!r || !c) && (r || c)) throw BadInitializers( ); rows = r; cols = c; row = new Array1D<T> [r]; for (int i = 0; i < r; i++) row [i].ReSize(c); } Program 4.7 Constructor for a two-dimensional array template <class T> Array2D<T>::Array2D(const Array2D<T>& m) { rows = m.rows; cols = m.cols; row = new Array1D<T> [rows]; for (int i = 0; i < rows; i++) row[i] = m.row[i]; } Program 4.8 Copy constructor for two-dimensional arrays template<class T> Array1D<T>& Array2D<T>::operator [ ] (int i) const { if (i < 0 || i >= rows) throw OutOfBounds( ); return row[i]; } Program 4.9 Overloading [ ] for a two-dimensional array
template <class T>Array2D<T> Array2D<T>::operator - (const Array2D<T>& m) const { if (rows != m.rows || cols != m.cols) throw SizeMismatch( ); Array2D<T> w(rows,cols); for (int i = 0; i < rows; i++) w.row[i] = row[i] - m.row[i]; return w; } Program 4.10 Subtraction template <class T> Array2D<T> Array2D<T>::operator *(const Array2D<T>& m) const { if (cols != m.rows) throw SizeMismatch(); Array2D<T> w (rows, m.cols); for (int i = 0; i < rows; i++) for (int j = 0; j < m.cols; j++) { T sum = (*this )[i][0] * m[0][j]; for (int k = 1; k < cols; k++) sum += (*this )[ i ][ k ] * m[ k ][ j ]; w [i] [j] = sum;} return w; } Program 4.11 Matrix multiplication
4.2 MATRICES4.2.1 Definitions and Operations MT(i,j) = M(j,i), 1<i<n, 1<j<m C(i,j) = A (i,j) +B (i,j) c (i,j) =∑ A (i,k) *B (k,j)
4.2.2 The Class Matrix • An m x n matrix M all of whose elements are integer may be represented as a two-dimensional integer array int x[m][n] or Array2D <int> x[m] [n]
Program 4.12 The class Matrix template <class T> class Matrix { 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; //unary+ Matrix<T>operator + (const Matrix<T>& m)const; Matrix<T>operator - ( )const;// unary minus Matrix<T>operator - (constMatrix<T>& m)const; Matrix<T>operator * (constMatrix<T>& m)const; Matrix<T>&operator += (constT&x); private: int rows, cols; T *element; };
Program 4.13 Matrix constructor template <class T> Matrix<T> :: Matrix (int r, int c) { if (r < 0 || c < 0) throw BadInitializers( ); if ((!r || !c) && (r || c)) throw BadInitializers( ); rows = r; cols = c; element = new T [r * c]; } Program 4.14 Indexing a matrix template <class T> T& Matrix<T> :: operator ( ) (int i, int j) const { // “( )” can take any number of parameters. if (i < 1 || i > rows || j < 1 || j > cols) throw OutOfBounds ( ); return element[(i - 1) * cols + j - 1]; }
template <class T> Matrix<T> Matrix<T>: :operator - (const Matrix<T>& m) const { // Return (*this) - m. if (rows != m.rows || cols != m.cols) throw SizeMismatch(); // create result matrix w Matrix<T> w(rows, cols); for (int i = 0; i < rows * cols; i++) w.element[i] = element[i] - m.element[i]; return w; } Program 4.15 Matrix subtraction
template <class T> Matrix<T> Matrix<T>::operator * (const Matrix<T>& m) const { if (cols != m.rows) throw SizeMismatch(); Matrix<T> w(rows, m.cols); // result matrix 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++; cm += m.cols; // next in column j of m sum += element[ct] * m.element[cm]; } w.element[cw++] = sum; ct -= cols - 1; cm = j; } ct += cols; cm = 0; } return w; } Program 4.16 Matrix multiplication
4.3 SPECIAL MATRIXES4.3.1 Definitions and Applications • Square matrix • Diagonal(对角矩阵) • Tridiagonal(三对角矩阵) • Lower triangular(下三角矩阵) • Upper triangular (上三角矩阵) • Symmetric (对称矩阵)
4.3.2 Diagonal Matrices Program 4.17 The class DiagonalMatrix template <class T> class DiagonalMatrix { public: DiagonalMatrix (int size = 10) {n=size; d=newT [n];} ~DiagonalMatrix( ) { delete [ ] d; } DiagonalMatrix<T>& Store (const T& x, int i, int j); T Retrieve (int i,int j) const; private: int n; T *d; };
template <class T> DiagonalMatrix<T>& DiagonalMatrix<T>::Store(const T& x, int i, int j) { if (i < 1 || j < 1 || i > n || j > n) throw OutOfBounds(); if (i != j && x != 0) throw MustBeZero(); if (i == j) d[i-1] = x; return *this ; } template <class T> T DiagonalMatrix<T>::Retrieve(int i, int j) const { // Retrieve D(i,j). if (i < 1 || j < 1 || i > n || j > n) throw OutOfBounds( ); if (i == j) return d[i-1]; else return 0; }
4.3.3 Tridiagonal Matrix • In an n*n trdiagonal matrix T. the nonzero elements lie on one of the three diagonals: • Main diagonal – for this, i = j. • Diagonalbelow main diagonal – for this, i = j+1. • Diagonal above mian diagonal – for this, i = j-1. • t [0:9]=[2,1,3,1,3,5,2,7,9,0] t = [2,3,1,1,5,3,2,9,7,0] t = [3,5,9,2,1,2,0,1,3,7]
Program 4.18 The class TridiagonalMatrix template <class T>class TridiagonalMatrix { public: TridiagonalMatrix(int size = 10) { n = size; t = new T [3*n-2];} TridiagonalMatrix( ) { delete [ ] t; } TridiagonalMatrix<T>& Store (const T& x, int i, int j); T Retrieve(int i, int j) const ; private: int n; T *t; };
template <class T>TridiagonalMatrix<T>& TridiagonalMatrix<T>::Store(const T& x, int i, int j) { if (i < 1 || j < 1 || i > n || j > n) throw OutOfBounds(); switch (i - j) { case 1: t[i - 2] = x; break ; case 0: t[n + i - 2] = x; break ; case -1: t[2 * n + i - 2] = x; break ; default: if (x != 0) throw MustBeZero(); } return *this ; }
template <class T> T TridiagonalMatrix<T>::Retrieve(int i, int j) const { if (i < 1 || j < 1 || i > n || j > n) throw OutOfBounds(); switch (i - j) { case 1: return t[i - 2]; case 0: return t[n + i - 2]; case -1: return t[2 * n + i - 2]; default: return 0; } } Program 4.18 The class TridiagonalMatrix
Program 4.19 The class LowerMatrix template <class T> class LowerMatrix { public : LowerMatrix(int size = 10){ n = size; t = new T[n*(n+1)/2]; } ~LowerMatrix( ) { delete [ ] t; } LowerMatrix<T>& Store ( const T& x, int i, int j ); T Retrieve(int i, int j) const ; private : int n; // matrix dimension T *t; // 1D array for lower triangle };
template <class T> LowerMatrix<T>& LowerMatrix<T>::Store(const T& x, int i, int j) { if (i < 1 || j < 1 || i > n || j > n) throw OutOfBounds( ); if (i >= j) t[i*(i-1)/2+j-1] = x; else if (x != 0) throw MustBeZero(); return *this ; } template <class T> T LowerMatrix<T>::Retrieve(int i, int j) const { if (i < 1 || j < 1 || i > n || j > n) throw OutOfBounds( ); if (i >= j) return t[i*(i-1)/2+j-1]; else return 0; }
4.4 Sparse Matrices(稀疏矩阵)4.4.1 Motivation • 什么是稀疏矩阵?矩阵的许多元素为0 • 如何进行压缩存储?三元组表示(i, j, aij) • An m x n matrix is said to be sparse if many of its elements are zero. A matrix that is not sparse is dense.
template <class T> class SparseMatrix { friend ostream& operator << (ostream&, const SparseMatrix<T>&); friend istream& operator >> (istream&, SparseMatrix<T>&); public: SparseMatrix(int maxTerms = 10); ~SparseMatrix() { delete [ ] a; } void Transpose(SparseMatrix<T> &b) const; void Add(const SparseMatrix<T> &b, SparseMatrix<T> &c) const; private : void Append(const Term<T>& t); int rows, cols, terms, MaxTerms; Term<T> *a; }; Program 4.20 The class SparseMatrix
Program 4.21 SparseMatrix constructor template <class T> SparseMatrix<T>::SparseMatrix(int maxTerms) { if (maxTerms < 1) throw BadInitializers(); MaxTerms = maxTerms; a = new Term<T> [MaxTerms]; terms = rows = cols = 0; }
template <class T> ostream& operator << (ostream& out, const SparseMatrix<T>& x) { out << "rows=" << x.rows << "columns=“ << x.cols << endl; out << "nonzero terms = " << x.terms << endl; for (int i = 0; i < x.terms; i++) out<<"a("<< x.a[i].row<<', '<<x.a[i].col<<") ="<<x.a[i].value<<endl; return out; } template <class T> istream& operator >>(istream& in, SparseMatrix<T>& x) { cout << "Enter number of rows, columns, and terms" << endl; in >> x.rows >> x.cols >> x.terms; if (x.terms > x.MaxTerms) throw NoMem( ); for (int i = 0; i < x.terms; i++) { cout << "Enter row, column, and value of term" << (i + 1) << endl; in >> x.a[i].row >> x.a[i].col >> x.a[i].value; } return in; } Program 4.22 SparseMatrix input and output Codes
template <class T> //转置结果在b中 void SparseMatrix<T>::Transpose(SparseMatrix<T> &b) const { if (terms > b.MaxTerms) throw NoMem(); b.cols = rows; b.rows = cols; b.terms = terms; //设转置特征 int *ColSize, *RowNext; ColSize = new int [cols + 1]; RowNext = new int [rows + 1]; for (int i = 1; i <= cols; i++) ColSize[i] = 0; for (int i = 0; i < terms; i++) ColSize[a[i].col]++; RowNext[1] = 0; for (int i = 2; i <= cols; i++) RowNext[i] = RowNext[i - 1] + ColSize[i - 1]; for (int i = 0; i < terms; i++) { //执行转置 int j = RowNext[a[i].col]++; b.a[j].row = a[i].col; b.a[j].col = a[i].row; b.a[j].value = a[i].value; } } Program 4.23 Transposing a sparse matrix
Program 4.24 Appending a non-zero term template <class T> void SparseMatrix<T>::Append(const Term<T>& t) { // Append a nonzero term t to *this. if (terms >= MaxTerms) throw NoMem(); a[terms] = t; terms++; }
Program 4.25 Adding two sparse matrices template<class T> // C =(*this) + b void SparseMatrix<T>::Add( const SparseMatrix<T>&b, SparseMatrix<T> &c) const { if (rows != b.rows || cols != b.cols) throw SizeMismatch( ); c.rows = rows; c.cols = cols; c.terms = 0; int ct = 0, cb = 0; while (ct<terms && cb<b.terms) {// 在*this和b中遍历 int indt = a[ct].row * cols + a[ct].col; int indb = b.a[cb].row * cols + b.a[cb].col; if (indt < indb) { c.Append(a[ct]); ct++; }
else { if (indt == indb) { if (a[ct].value + b.a[cb].value) { term <T> t; t.row = a[ct].row;t.col=a[ct].col; t.value=a[ct].value+b.a[cb].value; c.append(t);} ct++; cb++;} else { c.append(b.a[cb]); cb++; } } } for (; ct<terms; ct++) c.append (a[ct]); for (; cb<b.terms; cb++) c.append(b.a[cb]); } Program 4.25 Adding two sparse matrices
4.4.3 Linked Representation • A shortcoming of the one-dimensional array representation of a sparse matrix is that we need to know the number of nonzero terms in each of the sparse matrices.
1. The representation(含行指针的链表) 0 0 0 2 0 0 1 0 0 6 0 0 7 0 0 3 0 0 0 9 0 8 0 0 0 4 5 0 0 0 0 0 • Chain Node Types • Chain <Cnode<T>>
template <class T> class CNode { public: int operator != (const CNode<T>& y) { return (value != y.value);} void Output(ostream& out) const { out << "column " << col << " value " << value; } private: int col; T value; }; template <class T> ostream& operator << (ostream& out, const CNode<T>& x) { x.Output(out); out << endl; return out; }
template <class T> class HeadNode { public: int operator !=(const HeadNode<T>& y){return (row!=y.row);} void Output(ostream& out) const { out << "row " << row; } private : int row; Chain<CNode<T>> a; }; // row chain template <class T> ostream& operator (ostream& out, const HeadNode<T>& x) { x.Output(out); out << endl; return out; } Program 4.26 Chain nodes used in sparse matrix representation
3. The Class LinkedMatrix template <class T> class LinkedMatrix { public: LinkedMatrix( ) { }; ~LinkedMatrix( ) { } ; void Transpose(LinkedMatrix<T> &b) const ; void Add(const LinkedMatrix<T> &b, LinkedMatrix<T>&c)const ; private : int rows, cols; Chain<HeadNode<T> > a; }; Program 4.27 Class definition for a linked sparse matrix
4. Overloading >> template<class T> istream& operator >> (istream& in, LinkedMatrix<T>& x) { x.a.Erase( ); int terms; cout << "Enter number of rows,columns," << "and terms" << endl; in >> x.rows >> x.cols >> terms; HeadNode<T> H; H.row = 0; for (int i = 1; i <= terms ; i++) { cout<<"Enter row,column and "<<"value of term"<< i << endl; int row, col; T value; in >> row >> col >> value; if (row > H.row) { if (H.row) x.a.Append(H);