所有特殊矩阵 :ADT模板类封装( 稀疏矩阵 | 三角矩阵 | 三对角矩阵 | 十字矩阵 )

目录

前置数据结构定义

顺序表

单链表

矩阵元素三元组结构【稀疏矩阵】

矩阵链式元素结构 【十字链表】

稀疏矩阵

十字矩阵

下三角矩阵

三对角矩阵

对角矩阵


前置数据结构定义

顺序表

template <class T> class arrayList
	: public linearList< T >
#include <iostream>
#include <sstream>

#include <stdexcept>
#include <exception>

#include <algorithm>
#include <iterator>
#include <type_traits>

#include <cstdint>
#include <cstddef>
#include <assert.h>

template<typename T> class arrayList;
template <typename value_type>
bool operator<( const arrayList<value_type>& lhs,
			     const arrayList<value_type>& rhs){
	register int i;
	for(i = 0; i < std::min( lhs.listSize, rhs.listSize ); ++i)
		if( !( *( lhs.elements + i ) == *(rhs.elements + i) ) )
			return *( lhs.elements + i) < *(rhs.elements + i);
	return lhs.listSize < rhs.listSize;
}

template <typename value_type>
bool operator==( const arrayList<value_type>& lhs,
			     const arrayList<value_type>& rhs){
	if( !( lhs.listSize == rhs.listSize ) ) return false;
	register int i;
	for(i = 0; i < lhs.listSize; ++i)
		if( !( *( lhs.elements + i ) == *(rhs.elements + i) ) )
			return false;
	return true;
}

template <typename value_type>
bool operator!=( const arrayList<value_type>& lhs,
			     const arrayList<value_type>& rhs){
	return !( lhs == rhs );
}

template < typename T >
std::ostream& operator<<( std::ostream& os, const arrayList< T >& x){
	x.output( os );
	return os;
}

template < class T > class linearList{
public:
	virtual ~linearList( void ) {};
	virtual bool empty( void ) const = 0;
	virtual std::size_t size( void ) const = 0;
	virtual T& get( int theIndex ) const = 0;
	virtual int indexOf( const T& theElement ) const = 0;
	virtual void erase( int theIndex ) = 0;
	virtual void insert( int theIndex, const T& theElement ) = 0;
	virtual void output( std::ostream& os ) const = 0;
};

template <class T> class arrayList
	: public linearList< T >{
		friend bool operator==<T>( const arrayList<T>&,
					     const arrayList<T>&);
		friend bool operator< <T>( const arrayList<T>&,
					     const arrayList<T>&);
		friend bool operator!=<T>( const arrayList<T>&,
					     const arrayList<T>&);
		friend std::ostream& operator<< <T>( std::ostream&,
					     const arrayList<T>&);
class iterator{
	public:
		typedef std::bidirectional_iterator_tag iterator_category;
		typedef T value_type;
		typedef std::ptrdiff_t difference_type;
		typedef value_type* pointer;
		typedef value_type& reference;

		iterator(pointer thePosition = nullptr) : position( thePosition ) {}

		reference operator*( void ) const { return *position; }
		pointer operator->( void ) const { return &(*position); }

		iterator& operator++( void ) {
			++position;
			return *this;
		}
		iterator& operator--( void ){
			--position;
			return *this;
		}
		iterator operator++( int dummy ){
			iterator tmp = *this;
			++position;
			return tmp;
		}
		iterator operator--( int dummy ){
					iterator tmp = *this;
					--position;
					return tmp;
		}

		bool operator!=( const iterator rhs ) const{
			return position != rhs.position;
		}
		bool operator==( const iterator rhs ) const{
					return position == rhs.position;
		}
	protected:
		pointer position;
};
public:
	arrayList(int initialCapacity = 10, std::size_t Scaler = 2);
	arrayList( const arrayList< T >&);
	~arrayList( void ){
		if(elements) delete[]elements;
		elements = nullptr;
	}
	virtual bool empty( void ) const { return listSize == 0; }
	virtual std::size_t size( void ) const { return listSize; }
	virtual T& get( int theIndex ) const;
	virtual int indexOf( const T& theElement ) const;
	virtual void erase( int theIndex );
	virtual void insert( int theIndex, const T& theElement );
	virtual void output( std::ostream& os ) const;
	
	T& operator[]( std::size_t position ) const;

	std::size_t capacity( void ) const { return arrayLength; }

	iterator begin( void ){ return iterator( elements ); }
	iterator end( void ){ return iterator( elements + listSize ); }
	
	inline void trimToSize( void );
	void setSize( std::size_t _Size );
	
protected:
	void checkIndex(int theIndex) const;
	T* elements { nullptr };
	std::size_t arrayLength { 10 };
	std::size_t listSize { 0 };
	uint8_t Scaler;
};

template < class T >
void arrayList< T >::checkIndex( int theIndex ) const{
	if( theIndex < 0 || theIndex >= listSize ){
		std::ostringstream oss;
		char buf[ 64 ];
		sprintf( buf, "given index = %d; size = %d", theIndex, listSize );
		oss << buf;
		throw std::invalid_argument( oss.str() );
	}
	return;
}

template < class T >
arrayList< T >::arrayList(int initialCapacity, std::size_t Scaler)
:Scaler( Scaler ){
	if( initialCapacity < 1 ){
		std::ostringstream oss;
		char buf[ 64 ];
		sprintf( buf, "initial capacity = %d Must be > 0", initialCapacity);
		oss << buf;
		throw std::invalid_argument( oss.str() );
	}
	arrayLength = initialCapacity;
	elements = new T[ arrayLength ];
}

template < class T >
inline void arrayList< T >::trimToSize( void ){
	changeLength1D( elements, arrayLength, std::max( listSize, 1ULL ) );
	arrayLength = std::max( listSize, 1ULL );
}

template <class T>
void arrayList< T >::setSize( std::size_t _Size ){
	if( listSize > _Size )
		for( std::ptrdiff_t i = _Size; i < listSize; ++i)
			delete (elements + i);
	listSize = _Size;
}

template <class T>
T& arrayList< T >::operator[]( std::size_t position ) const{
	checkIndex( position );
	return *(elements + position);
}

template < class T >
arrayList< T >::arrayList( const arrayList< T >& theList )
	:arrayLength( theList.arrayLength )
	,listSize( theList.listSize )
	,elements( new T[ arrayLength ])
{
	std::copy(theList.elements, theList.element + listSize, elements );
}

template < class T >
int arrayList< T >::indexOf( const T& theElement ) const{
	int ret {};
	return
		( int )( ( ret =
			std::find(elements, elements + listSize, theElement) - elements) )
				== listSize ? -1 : ret;
}

template < typename T >
void arrayList< T >::erase(int theIndex ){
	checkIndex( theIndex );
	std::copy( elements + theIndex + 1, elements + listSize, elements + theIndex );
	elements[ --listSize ].~T();
}

template < typename T >
void arrayList< T >::insert( int theIndex, const T& theElement ){
	checkIndex( theIndex );
	if(listSize == arrayLength ){
		changeLength1D( elements, arrayLength, arrayLength * Scaler );
		arrayLength *= Scaler;
	}
	std::copy_backward( elements + theIndex, elements + listSize, elements + listSize+1 );
	elements[ theIndex ] = theElement;
}

template < typename T >
void arrayList< T >::output( std::ostream& os ) const{
	std::copy( elements, elements + listSize, std::ostream_iterator< T >( os, "	") );
}

template < typename value_type >
void changeLength1D( value_type*& pArray,
					 const signed long& N,
					 const signed long& M )
{
//	static_assert(typename std::is_copy_constructible<value_type>::value, "requires copying");
	if( nullptr == pArray )
		throw std::domain_error( "array is nullptr" );
	if( N < 0 || M < 0)
		throw std::invalid_argument( "illegalParameterValue N|M given" );
	std::size_t checkedN  = static_cast< std::size_t >( N );
	std::size_t checkedM  = static_cast< std::size_t >( M );
	value_type* temp = new value_type[ checkedM ];
	std::copy( pArray, pArray + std::min( checkedN, checkedM ), temp );
	delete [] pArray;
	pArray = temp;
}

template < class T >
T& arrayList< T >::get( int theIndex ) const{
	checkIndex( theIndex );
	return elements[ theIndex ];
}

template < typename value_type, std::size_t formerN, std::size_t formerM >
value_type** chanegeLeagth2D( value_type (&_Matrix)[ formerN ][ formerM],
					  const signed long& newN,
					  const signed long& newM){
	assert(newN > 0 && newM > 0 || "invalid argument nagetive N | M given");
//	static_assert(typename std::is_copy_constructible<value_type>::value, "requires copying");
	value_type ** _ScaledMatrix = new value_type*[ newN ];
	for( std::ptrdiff_t i = 0; i < newM; ++i) _ScaledMatrix[ i ] = new value_type[ newM ];
	int i,j;
	std::size_t checkedN  = static_cast< std::size_t >( newN );
	std::size_t checkedM  = static_cast< std::size_t >( newM );
	for(i = 0; i < std::min( formerN, checkedN ); ++i)
		for(j = 0; j < std::min( formerM, checkedM ); ++j)
			_ScaledMatrix[i][j] = _Matrix[i][j];
	return _ScaledMatrix;
}

template < typename InputIterator >
void myCopy(InputIterator begIt, InputIterator endIt, InputIterator resIt ){
	while( !( begIt == endIt ) )
		*resIt++ = *begIt++;
}

int main( void ){
	int *pArray = new int[5] { 1, 2, 3, 4, 5 };
	changeLength1D( pArray, 5L, 10L );
	int i;
	for(i = 0;i < 10;++i) std::clog << *( pArray + i ) << '
';
	
	constexpr int N { 5 };
	int *pEnd = pArray + N;
	for( std::ptrdiff_t i { N }; i > 0; --i )
		std::clog << ( *( pEnd - i ) = i ) << '	';
	std::endl( std::cout );
	return 0;
}

单链表

template < class T > class chain :
     public linearList< T >;
#include <iostream>
#include <sstream>
#include <cstdio>
#include <iterator>
#include <type_traits>



template < class T > class linearList{
public:
	virtual ~linearList( void ) {};
	virtual bool empty( void ) const = 0;
	virtual std::size_t size( void ) const = 0;
	virtual T& get( int theIndex ) const = 0;
	virtual int indexOf( const T& theElement ) const = 0;
	virtual void erase( int theIndex ) = 0;
	virtual void insert( int theIndex, const T& theElement ) = 0;
	virtual void output( std::ostream& os ) const = 0;
};

template < class T > class extendedLinearList
: public linearList< T >
{
public:
	virtual ~extendedLinearList( void ){ }
	virtual void clear( void ) = 0;
	virtual void push_back( const T& theElement ) = 0;
};


template < class T> struct chainNode{
	T element;
	chainNode< T > *next { nullptr };
	
	chainNode( void ) {}
	chainNode( const T& element )
		:element( element )
		{}
	chainNode( const T& element, const chainNode< T > *next )
		:chainNode( element )
		{ this->next = next;}
};

template < typename T > class chain;
template < typename T >
std::ostream& operator<<( std::ostream& os, const chain< T >& x){
	x.output( os );
	return os;
}


template < class T > class chain : public linearList< T >{
class iterator{
	public:
		typedef std::forward_iterator_tag iterator_category;
		typedef T value_type;
		typedef chainNode< value_type >* pointer;
		typedef chainNode< value_type >& reference;

		iterator( pointer theNode = nullptr) : node( theNode ) {}

		reference operator*( void ) const { return &node->element; }
		pointer operator->( void ) const { return node->element; }

		iterator& operator++( void ) {
			node = node->next;
			return *this;
		}
		iterator operator++( int dummy ){
			iterator tmp = *this;
			node = node->next;
			return tmp;
		}

		bool operator!=( const iterator rhs ) const{
			return node != rhs.node;
		}
		bool operator==( const iterator rhs ) const{
					return node == rhs.node;
		}
	protected:
		pointer node;
};
public:
	chain( const chain< T >& );
	~chain( void );
	
	virtual bool empty( void ) const { return listSize == 0; }
	virtual std::size_t size( void ) const { return listSize; }
	
	virtual T& get( int theIndex ) const;
	virtual int indexOf( const T& theElement ) const;
	virtual void erase( int theIndex );
	virtual void insert( int theIndex, const T& theElement );
	virtual void output( std::ostream& os ) const;
	
	iterator begin( void ){ return iterator( firstNode ); }
	iterator end( void ){ return iterator(); }
	
protected:
	void checkIndex( int theIndex ) const;
	chainNode< T > *firstNode { nullptr };
	std::size_t listSize { 0 };
};
template < class  T >
chain< T >::chain( const chain< T >& theList)
:listSize( theList.listSize )
{
	if( !listSize ) return;
	chainNode< T > *sourceNode = theList.firstNode;
	firstNode = new chainNode< T >( sourceNode->element );
	chainNode< T > *targetNode = firstNode;
	while( sourceNode ){
		targetNode->next = new chainNode< T >( sourceNode->element );
		targetNode = targetNode->next;
		sourceNode = sourceNode->next;
	}
}

template < class T >
void chain< T >::checkIndex( int theIndex ) const{
	if( theIndex < 0 || theIndex >= listSize ){
		std::ostringstream oss;
		char buf[ 64 ];
		sprintf( buf, "given index = %d; size = %d", theIndex, listSize );
		oss << buf;
		throw std::invalid_argument( oss.str() );
	}
	return;
}

template < class T >
T& chain< T >::get( int theIndex ) const{
	checkIndex( theIndex );
	chainNode< T > *currentNode = firstNode;
	for( register int i { 0 }; i < theIndex; ++i)
		currentNode = currentNode->next;
	return currentNode->element;
}

template < class T >
int chain< T >::indexOf( const T& theElement ) const{
	chainNode< T > *currentNode = firstNode;
	int index = 0;
	while( currentNode && !( currentNode->element == theElement ) ){
		currentNode = currentNode->next;
		++index;
	}
	return currentNode ? index : -1;
}

template < class T >
void chain< T >::erase( int theIndex ){
	checkIndex( theIndex );
	chainNode< T > *deleteNode;
	if( !theIndex ){
		deleteNode = firstNode;
		firstNode = firstNode->next;
	}else{
		chainNode< T > *p =firstNode;
		for( register int i { 0 }; i < theIndex; ++i )
			p = p->next;
		deleteNode = p->next;
		p->next = p->next->next;
	}
	listSize--;
	delete deleteNode;
}

template < class T >
void chain<T>::insert( int theIndex, const T& theElement ){
	checkIndex( theIndex );
	if( !theIndex ) firstNode = new chainNode< T >( theElement, firstNode );
	else{
		chainNode< T > *p = firstNode;
		for( register int i { 0 }; i < theIndex; ++i )
			p = p->next;
		p->next = new chainNode< T >( theElement, p->next );
	}
	listSize++;
}

template < class T >
void chain< T >::output( std::ostream& os ) const{
	for( chainNode< T > *currentNode = firstNode;
		 currentNode;
		 currentNode = currentNode->next)
			os << currentNode->element << '	';
}

int main( void ){

	return 0;
}

矩阵元素三元组结构【稀疏矩阵】

// 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

矩阵链式元素结构 【十字链表】

// element types used by class linkedMatrix

#ifndef matrixElements_
#define matrixElements_

#include "extendedChain.h"

using namespace std;

template<class T>
struct rowElement 
{
   int col;
   T value;

   bool operator !=(const rowElement<T>& y)
      {return (value != y.value);}
   void output(ostream& out) const
      {out << "column " << col 
           << " value " << value << endl;}
};

template<class T>
ostream& operator<<(ostream& out, const rowElement<T>& x)
   {x.output(out); return out;}

template<class T>
struct headerElement
{
      int row;
      extendedChain<rowElement<T> > rowChain;

      bool operator !=(const headerElement<T>& y)
         {return (row != y.row);}
      void output(ostream& out) const
         {out << "row " << row << endl << "  " << rowChain << endl;}
};

template<class T>
ostream& operator<<(ostream& out,
                    const headerElement<T>& x)
   {x.output(out); return out;}

#endif

稀疏矩阵

// sparse matrix using an extended array list

#ifndef sparseMatrix_
#define sparseMatrix_

#include <iostream>
#include "matrixTerm.h"
#include "extendedArrayList.h"
#include "myExceptions.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 <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 (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 (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 (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
   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();

   // 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

十字矩阵

// linked representation of a sparse matrix

#ifndef linkedMatrix_
#define linkedMatrix_

#include <iostream>
#include "extendedChain.h"
#include "matrixElements.h"

using namespace std;

template<class T>
class linkedMatrix 
{
   friend ostream& operator<<
          (ostream&, linkedMatrix<T>&);
   friend istream& operator>>
          (istream&, linkedMatrix<T>&);
   public:
      linkedMatrix(){}
      ~linkedMatrix(){}
      void transpose(linkedMatrix<T> &b);
   private:
      int rows,       // number of rows in matrix
          cols;       // number of columns in matrix
      extendedChain<headerElement<T> > headerChain;
};

template<class T>
istream& operator>>(istream& in, linkedMatrix<T>& x)
{// Input matrix x from the stream in.
   x.headerChain.clear();
       // delete all nodes from x

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

   // create fictional row zero
   headerElement<T> header;  // header for current row
   header.row = 0;           // current row number

   // get terms of matrix x
   for (int i = 1; i <= terms; i++) 
   {
      // input next term
      cout << "Enter row, column, and value of term " 
           << i << endl;
      rowElement<T> *term = new rowElement<T>;
      int row;
      in >> row >> term->col >> term->value;

      // check if new term is part of current row
      if (row > header.row)
      {// start a new row
         // append header of current row to
         // header node chain only if row not zero
         if (header.row != 0)
            x.headerChain.push_back(header);

         // prepare header for new row
         header.row = row;
         header.rowChain.zero();
               // clear without deleting nodes
      }

      // add new term to row chain
      header.rowChain.push_back(*term);
   }

   // take care of last row of matrix
   if (header.row != 0)
      x.headerChain.push_back(header);
   header.rowChain.zero(); // save from chain destructor

   return in;
}

template<class T>
ostream& operator<<(ostream& out, linkedMatrix<T>& x)
{// Put matrix x into the output stream out.
   // output matrix dimensions
   out << "rows = " << x.rows << " columns = "
       << x.cols << endl << "  ";

   if (x.headerChain.empty())
   {
      out << "No non-zero terms" << endl;
      return out;
   }

   out << x.headerChain << endl;
   return out;
}

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

istream& operator>>(istream& in, linkedMatrix<int>& x)
{// Input matrix x from the stream in.
   x.headerChain.clear();
       // delete all nodes from x

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

   // create fictional row zero
   headerElement<int> header;  // header for current row
   header.row = 0;             // current row number

   // get terms of matrix x
   for (int i = 1; i <= terms; i++) 
   {
      // input next term
      cout << "Enter row, column, and value of term " 
           << i << endl;
      rowElement<int> *term = new rowElement<int>;
      int row;
      in >> row >> term->col >> term->value;

      // check if new term is part of current row
      if (row > header.row)
      {// start a new row
         // append header of current row to
         // header node chain only if row not zero
         if (header.row != 0)
            x.headerChain.push_back(header);

         // prepare header for new row
         header.row = row;
         header.rowChain.zero();
               // clear without deleting nodes
      }

      // add new term to row chain
      header.rowChain.push_back(*term);
   }

   // take care of last row of matrix
   if (header.row != 0)
      x.headerChain.push_back(header);
   header.rowChain.zero(); // save from chain destructor

   return in;
}

ostream& operator<<(ostream& out, linkedMatrix<int>& x)
{// Put matrix x into the output stream out.
   // output matrix dimensions
   out << "rows = " << x.rows << " columns = "
       << x.cols << endl << "  ";

   if (x.headerChain.empty())
   {
      out << "No non-zero terms" << endl;
      return out;
   }

   out << x.headerChain << endl;

   return out;
}
/****************************************************************/

template<class T>
void linkedMatrix<T>::transpose(linkedMatrix<T> &b)
{// Return transpose of *this as matrix b.
   b.headerChain.clear(); // delete all nodes from b

   // create bins to collect rows of b
   extendedChain<rowElement<T> > *bin;
   bin = new extendedChain<rowElement<T> > [cols + 1];

   // head node iterator
   extendedChain<headerElement<T> >::iterator
      ih = headerChain.begin(),
      ihEnd = headerChain.end();


   // copy terms of *this into bins
   while (ih != ihEnd)
   {// examine all rows
      int r = ih->row; // row number for row chain

      // row chain iterator
      extendedChain<rowElement<T> >::iterator
         ir = ih->rowChain.begin(),
         irEnd = ih->rowChain.end();


      rowElement<T> x;
      // terms from row r of *this go to column r of b
      x.col = r;

      while (ir != irEnd)
      {// copy a term from the row chain into a bin
         x.value = ir->value;
         // x will eventually be in row ir->col of transpose
         bin[ir->col].push_back(x);
         ir++;  // next term in row
      }

      ih++; // go to next row
   }

   // set dimensions of transpose
   b.rows = cols;
   b.cols = rows;

   // assemble header chain of transpose
   headerElement<T> h;
   // scan bins
   for (int i = 1; i <= cols; i++)
      if (!bin[i].empty())
      {// row i of transpose
         h.row = i;
         h.rowChain = bin[i];
         b.headerChain.push_back(h);
         bin[i].zero(); // save from destructor
      }

   h.rowChain.zero();   // save from destructor

   delete [] bin;
}

#endif

下三角矩阵

// lower triangle matrix
#ifndef lowerTriangularMatrix_
#define lowerTriangularMatrix_


#include "myExceptions.h"

using namespace std;

template<class T>
class lowerTriangularMatrix 
{
   public:
      lowerTriangularMatrix(int theN = 10);
      ~lowerTriangularMatrix() {delete [] element;}
      T get(int, int) const;
      void set(int, int, const T&);
   private:
      int n;       // matrix dimension
      T *element;  // 1D array for lower triangle
};


template<class T>
lowerTriangularMatrix<T>::lowerTriangularMatrix(int theN)
{// Constructor.
   // validate theN
   if (theN < 1)
       throw illegalParameterValue("Matrix size must be > 0");

   n = theN;
   element = new T [n * (n + 1) / 2];
}
   
template <class T>
T lowerTriangularMatrix<T>::get(int i, int j) const
{// Return (i,j)th element of matrix.
   // validate i and j
   if ( i < 1 || j < 1 || i > n || j > n)
       throw matrixIndexOutOfBounds();

   // (i,j) in lower triangle iff i >= j
   if (i >= j)
      return element[i * (i - 1) / 2 + j - 1];
   else
      return 0;
}

template<class T>
void lowerTriangularMatrix<T>::set(int i, int j, const T& newValue)
{// Store newValue as (i,j)th element.
   // validate i and j
   if ( i < 1 || j < 1 || i > n || j > n)
       throw matrixIndexOutOfBounds();


   // (i,j) in lower triangle iff i >= j
   if (i >= j)
      element[i * (i - 1) / 2 + j - 1] = newValue;
   else
      if (newValue != 0)
         throw illegalParameterValue
               ("elements not in lower triangle must be zero");
}

#endif

三对角矩阵

// tridiagonal matrix

#ifndef tridiagonal_
#define tridiagonal_


#include "myExceptions.h"

using namespace std;

template<class T>
class tridiagonalMatrix 
{
   public:
      tridiagonalMatrix(int theN = 10);
      ~tridiagonalMatrix() {delete [] element;}
      T get(int, int) const;
      void set(int, int, const T&);
   private:
      int n;       // matrix dimension
      T *element;  // 1D array for tridiagonal
};

template<class T>
tridiagonalMatrix<T>::tridiagonalMatrix(int theN)
{// Constructor.
   // validate theN
   if (theN < 1)
       throw illegalParameterValue("Matrix size must be > 0");

   n = theN;
   element = new T [3 * n - 2];
}

template <class T>
T tridiagonalMatrix<T>::get(int i, int j) const
{// Return (i,j)th element of matrix.

   // validate i and j
   if ( i < 1 || j < 1 || i > n || j > n)
       throw matrixIndexOutOfBounds();
 
   // determine lement to return
   switch (i - j) 
   {
      case 1: // lower diagonal
              return element[i - 2];
      case 0: // main diagonal
              return element[n + i - 2];
      case -1: // upper diagonal
              return element[2 * n + i - 2];
      default: return 0;
   }
}

template<class T>
void tridiagonalMatrix<T>::set(int i, int j, const T& newValue)
{// Store newValue as (i,j)th element

   // validate i and j
   if ( i < 1 || j < 1 || i > n || j > n)
      throw matrixIndexOutOfBounds();

   switch (i - j) 
   {
      case 1: // lower diagonal
         element[i - 2] = newValue; break;
      case 0: // main diagonal
         element[n + i - 2] = newValue; break;
      case -1: // upper diagonal
         element[2 * n + i - 2] = newValue; break;
      default: if (newValue != 0)
                  throw illegalParameterValue
                        ("non-tridiagonal elements must be zero");
   }
}

#endif

对角矩阵

// diagonal matrix
#ifndef diagonalMatrix_
#define diagonalMatrix_


#include "myExceptions.h"

using namespace std;

template<class T>
class diagonalMatrix 
{
   public:
      diagonalMatrix(int theN = 10);
      ~diagonalMatrix() {delete [] element;}
      T get(int, int) const;
      void set(int, int, const T&);
   private:
      int n;       // matrix dimension
      T *element;  // 1D array for diagonal elements
};

template<class T>
diagonalMatrix<T>::diagonalMatrix(int theN)
{// Constructor.
   // validate theN
   if (theN < 1)
       throw illegalParameterValue("Matrix size must be > 0");

   n = theN;
   element = new T [n];
}
  
template <class T>
T diagonalMatrix<T>::get(int i, int j) const
{// Return (i,j)th element of matrix.
   // validate i and j
   if (i < 1 || j < 1 || i > n || j > n)
       throw matrixIndexOutOfBounds();

   if (i == j)
      return element[i-1];   // diagonal element
   else
      return 0;              // nondiagonal element
}

template<class T>
void diagonalMatrix<T>::set(int i, int j, const T& newValue)
{// Store newValue as (i,j)th element.
   // validate i and j
   if (i < 1 || j < 1 || i > n || j > n)
       throw matrixIndexOutOfBounds();

   if (i == j)
     // save the diagonal value
      element[i-1] = newValue;
   else
      // nondiagonal value, newValue must be zero
      if (newValue != 0)
         throw illegalParameterValue
               ("nondiagonal elements must be zero");
}

#endif