数据结构、算法与应用 C++语言描述 第7章习题
这一章的问题有很多重复性问题,选择了其中比较常用的一些问题进行了实现。
matrix类的相关问题
matrix.h
Q15-Q16
#include <iostream>
#include <algorithm>
template<class T>
class matrix
{
template <class U>
friend std::ostream& operator<<(std::ostream&, const matrix<U>&);
template <class U>
friend std::istream& operator>>(std::istream&, const matrix<U>&);
public:
matrix(int theRows = 0, int theColumns = 0);
matrix(const matrix<T>&);
~matrix() {delete [] elements;}
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&);
matrix<T>& operator-=(const T&);
matrix<T>& operator*=(const T&);
matrix<T>& operator/=(const T&);
matrix<T> reverse();
private:
int theRows, theColumns; // 矩阵的行数和列数
T *elements;
};
template<class T>
matrix<T>::matrix(int theRows, int theColumns)
{
if(theRows<0 || theColumns<0)
{
std::cout << "theRows or theColumns shouldn't be smaller than 0"<<std::endl;
return;
}
if((theRows==0 || theColumns==0) && (theRows!=0 || theColumns!=0))
{
std::cout << "Either theRows or theColumns shouldn't be 0"<<std::endl;
return;
}
// 创建矩阵
this->theRows = theRows;
this->theColumns = theColumns;
elements = new T [theRows * theColumns];
// 将初始化后的矩阵直接化为0
for(int i=0;i<theRows;i++)
{
for(int j=0;j<theColumns;j++)
elements[i*theColumns+j]=0;
}
}
// copy constructor
template<class T>
matrix<T>::matrix(const matrix<T>& m)
{
theRows = m.rows();
theColumns = m.columns();
elements = new T [theColumns * theRows];
// copy the element
std::copy(m.elements, m.elements+m.rows()*m.columns(), elements);
}
// 赋值运算符
template<class T>
matrix<T>& matrix<T>::operator=(const matrix<T>& m)
{
// 不能自己给自己赋值
if(this != &m)
{
delete [] elements;
theRows = m.rows();
theColumns = m.columns();
elements = new T [theColumns * theRows];
std::copy(m.elements, m.elements+m.rows()*m.columns(), elements);
}
return *this;
}
// 矩阵的索引从(1,1)开始.
// 返回的是索引,可以用于修改值.
template<class T>
T& matrix<T>::operator()(int i, int j) const
{
if(i>theRows || i<1 || j>theColumns || j<1)
{
std::cout << "index out of range." << std::endl;
return elements[0];
}
return elements[(i-1)*theColumns + j-1];
}
template<class T>
matrix<T> matrix<T>::operator+() const
{
return *this;
}
//非自加,返回第三方.
template<class T>
matrix<T> matrix<T>::operator+(const matrix<T>& m) const
{
if(theRows != m.theRows || theColumns != m.theColumns)
{
std::cout << "The shape of two matrix is not same." << std::endl;
return *this;
}
matrix<T> addMatrix(theRows, theColumns);
for(int i=0;i<theColumns*theRows;i++)
addMatrix.elements[i] = elements[i] + m.elements[i];
return addMatrix;
}
template<class T>
matrix<T> matrix<T>::operator-() const
{
matrix<T> w(theRows, theColumns);
for(int i=1;i<=theRows;i++)
{
for(int j=1;j<=theColumns;j++)
{
w(i,j)=-(*this)(i,j);
}
}
return w;
}
template<class T>
matrix<T> matrix<T>::operator-(const matrix<T>& m) const
{
matrix<T> w(theRows, theColumns);
for(int i=1;i<=theRows;i++)
{
for(int j=1;j<=theColumns;j++)
{
w(i,j)=(*this)(i,j) - m(i,j);
}
}
return w;
}
template<class T>
matrix<T> matrix<T>::operator*(const matrix<T>& m) const
{
if(theColumns!=m.theRows)
{
std::cout << "The shape of two matrix is not same." << std::endl;
return *this;
}
matrix<T> w(theRows, m.theColumns);
// 矩阵的索引都从1开始,和数组不同.
for(int i=1;i<=theRows;i++)
{
for(int j=1;j<=m.theColumns;j++)
{
for(int k=1;k<=theColumns;k++)
{
w(i,j) += (*this)(i,k)*m(k,j);
}
}
}
return w;
}
template<class T>
matrix<T>& matrix<T>::operator+=(const T& m)
{
for(int i=1;i<=theRows;i++)
{
for(int j=1;j<=theColumns;j++)
{
(*this)(i,j) += m;
}
}
return (*this);
}
template<class T>
matrix<T>& matrix<T>::operator-=(const T& m)
{
for(int i=1;i<=theRows;i++)
{
for(int j=1;j<=theColumns;j++)
{
(*this)(i,j) -= m;
}
}
return (*this);
}
template<class T>
matrix<T>& matrix<T>::operator*=(const T& m)
{
for(int i=1;i<=theRows;i++)
{
for(int j=1;j<=theColumns;j++)
{
(*this)(i,j) *= m;
}
}
return (*this);
}
template<class T>
matrix<T>& matrix<T>::operator/=(const T& m)
{
if(m!=0)
{
for(int i=1;i<=theRows;i++)
{
for(int j=1;j<=theColumns;j++)
{
(*this)(i,j) /= m;
}
}
}
return (*this);
}
template<class T>
std::ostream& operator<<(std::ostream& os, const matrix<T>& m)
{
if(m.theRows!=0)
{
for(int i=1;i<=m.theRows;i++)
{
for(int j=1;j<=m.theColumns;j++)
os << m(i,j) <<" ";
os << std::endl;
}
}
return os;
}
template <class U>
std::istream& operator>>(std::istream& is, const matrix<U>& m)
{
std::cout << "the rows: " << m.rows() << " " << "the columns: " << m.columns() << std::endl;
U num;
int i=1,j=1;
while(is >> num)
{
m(i,j) = num;
if(i == m.rows() && j == m.columns())
break;
j++;
if(j == m.columns()+1)
{
i++;
j=1;
}
}
return is;
}
template<class T>
matrix<T> matrix<T>::reverse()
{
matrix<T> w(theColumns, theRows);
for(int i=1;i<=theRows;i++)
{
for(int j=1;j<=theColumns;j++)
w(j,i) = (*this)(i,j);
}
return w;
}
关于下面两个继承类的数据类型的声明
由于在sparseMatrix中所用的基本数据类型matrixTerm,linkedMatrix中所用的基本数据类型rowElement和headerElement,他们都不是类似int或者float这种内置类型,而他们数据成员的类型(ArrayList、extendedChain)的模板参数T都需要有==、<<等操作。所以有两种方法解决这个问题的方法:
- 删除这些类型中可能需要这些操作的函数
- 在这些基本数据类型中添加这些操作
下面的sparseMatrix是删除了类型中需要这些操作的函数,linkedMatrix中是为结构体数据类型添加了这些操作
sparseMatrix类的相关问题
Q41/42/43/45
修改后的ArrayList.h
#ifndef ARRAYLIST_H
#define ARRAYLIST_H
#include "linearList.h"
#include <iostream>
#include <sstream>
#include <iterator>
#include <algorithm>
#include <utility>
// linearList<T> 要指出其是模板类
template <class T>
class arrayList : public linearList<T>
{
public:
// arrayList(int initialCapacity = 10); // 构造函数
// Q4
arrayList(int initialCapacity = 10, int increaseStep = 0);
arrayList(const arrayList<T> &);
~arrayList() {delete [] element;} // 释放元素数组指针所指向的内存
// 实现虚函数
bool empty() const {return listSize == 0;}
int size() const {return listSize;}
T& get(int theIndex) const override;
int indexOf(const T& theElement) const;
void erase(int theIndex);
void insert(int theIndex, const T& theElement);
// 获取数组总容量
int capacity() const {return arrayLength;}
// Q5
void trimToSize();
// Q6
void setSize(int newSize);
void reSet(int newSize);
// Q7
T& operator[](int x){return this->element[x];}
void operator=(const arrayList<T>& right);
// Q11
void push_back(const T& theElement);
void pop_back();
// Q15
T set(int theIndex, const T& theElement);
// Q16
void clear();
// 这种是内置迭代器类
// 还有一种把迭代器当做友元类
class myIterator
{
public:
myIterator(T* thePosition){position = thePosition;}
// 解引用操作符
T& operator*() const {return *position;}
T* operator->() const {return &*position;}
// 迭代器的值增加
myIterator& operator++(){++position;return position;}
myIterator operator++(int)
{
myIterator old=*this;
position++;
return old;
}
// 递减计算
myIterator& operator--(){--position;return position;}
myIterator operator--(int){
myIterator old = *this;
--position;
return old;
}
// +运算,不能使用引用返回的形式,因为结果是临时变量
myIterator operator+(const int& i){return position+i;}
// -运算
myIterator operator-(const int& i){return position-i;}
// 测试是否相等
bool operator!=(const myIterator Right) const{return position != Right.position;}
bool operator==(const myIterator Right) const{return position == Right.position;}
protected:
T* position;
};
myIterator begin(){return myIterator(element);} // 指向首元素
myIterator end() {return myIterator(element+listSize);} // 尾后迭代器
protected:
// 检查索引是否有效,无效则抛出异常
void checkIndex(int theIndex) const;
T* element;
int arrayLength; // 数组荣烺
int listSize; // 实际存储的数据的数量
int IncreaseStep = 0;
int InitialArrayLength;
};
// Q4
template<class T>
arrayList<T>::arrayList(int initialCapacity, int increaseStep)
{
if(initialCapacity < 1)
{
std::ostringstream s;
s << "Initial capacity = " << initialCapacity << " Must be > 0";
// throw s.str();
}
arrayLength = initialCapacity;
IncreaseStep = increaseStep;
element = new T[arrayLength];
InitialArrayLength = initialCapacity;
listSize = 0;
}
// 复制构造函数
template <class T>
arrayList<T>::arrayList(const arrayList<T> &theList)
{
arrayLength = theList.arrayLength;
listSize = theList.listSize;
IncreaseStep = theList.IncreaseStep;
element = new T[arrayLength];
InitialArrayLength = theList.InitialArrayLength;
// 将数组数据复制到当前位置
std::copy(theList.element, theList.element + listSize, element);
}
template <class T>
void arrayList<T>::checkIndex(int theIndex) const
{
if(theIndex < 0 || theIndex >= listSize)
{
std::ostringstream s;
s << "index= "<< theIndex << " size = " << listSize;
// throw s.str();
}
}
template <class T>
T& arrayList<T>::get(int theIndex) const
{
checkIndex(theIndex);
return element[theIndex];
}
template <class T>
void arrayList<T>::erase(int theIndex)
{
// 将后边的元素整体向前移动,然后删除空余的尾项
checkIndex(theIndex);
std::copy(element + theIndex + 1, element + listSize, element + theIndex);
element[--listSize].~T(); // 删除最后一个元素(已经被向前移动了一个了)
// Q20(1)
if(listSize < arrayLength/4)
{
int newSize = std::max(arrayLength/2, InitialArrayLength);
T* temp = new T[newSize];
changeLength1D(element, arrayLength, newSize);
arrayLength = newSize;
}
}
template <class T>
void arrayList<T>::insert(int theIndex, const T& theElement)
{
// 首先检查无效索引
checkIndex(theIndex);
// 有效索引,确定数组是否已满
if(listSize == arrayLength)
{
// 将已满的数组空间扩充到二倍
// Q4问题所要求的增长方式
// changeLength1D(element, arrayLength, 2 * arrayLength);
if(IncreaseStep == 0)
{
changeLength1D(element, arrayLength, 2 * arrayLength);
arrayLength *= 2;
}
else
{
changeLength1D(element, arrayLength, arrayLength + IncreaseStep);
arrayLength += IncreaseStep;
}
}
// 将数组元素向右移动一个位置
// 从后往前按序移动
std::copy_backward(element + theIndex, element + listSize, element + listSize + 1);
element[theIndex] = theElement;
listSize++;
}
template <class T>
void arrayList<T>::trimToSize()
{
int length = std::max(listSize, 1);
changeLength1D(element, arrayLength, length);
arrayLength = length;
listSize = length;
}
template <class T>
void arrayList<T>::setSize(int newSize)
{
int newlistsize = newSize;
if(newSize < listSize)
{
for (;newSize < listSize; newSize++)
element[newSize].~T();
// element[newSize] = 0;
listSize = newlistsize;
}
}
template <class T>
void arrayList<T>::reSet(int newSize)
{
changeLength1D(element, arrayLength, newSize);
arrayLength = newSize;
listSize = newSize;
}
template <class T>
void arrayList<T>::operator=(const arrayList<T>& theList)
{
arrayLength = theList.arrayLength;
listSize = theList.listSize;
T* deleteArray = element;
element = new T[arrayLength];
// 将数组数据复制到当前位置
std::copy(theList.element, theList.element + listSize, element);
delete [] deleteArray;
}
template <class T>
void arrayList<T>::push_back(const T& theElement)
{
// 有效索引,确定数组是否已满
if(listSize == arrayLength)
{
if(IncreaseStep == 0)
{
changeLength1D(element, arrayLength, 2 * arrayLength);
arrayLength *= 2;
}
else
{
changeLength1D(element, arrayLength, arrayLength + IncreaseStep);
arrayLength += IncreaseStep;
}
}
element[listSize] = theElement;
listSize++;
}
template <class T>
void arrayList<T>::pop_back()
{
if(listSize > 0)
{
--listSize;
element[listSize].~T();
}
// Q20(1)
if(listSize < arrayLength/4)
{
int newSize = std::max(arrayLength/2, InitialArrayLength);
T* temp = new T[newSize];
changeLength1D(element, arrayLength, newSize);
arrayLength = newSize;
}
}
template <class T>
T arrayList<T>::set(int theIndex, const T& theElement)
{
T temp = element[theIndex];
element[theIndex] = theElement;
return temp;
}
template <class T>
void arrayList<T>::clear()
{
while (listSize)
pop_back();
}
#endif
spareseMatrix.h
#include <iostream>
#include <algorithm>
#include "arrayList.h"
template <class T>
struct matrixTerm
{
// data member
T element;
unsigned int rowIndex, columnIndex;
// function
matrixTerm() {}
matrixTerm(unsigned int row, unsigned int column, const T& element)
{
this->element=element;
rowIndex=row;
columnIndex=column;
}
bool operator==(const matrixTerm<T> &m)
{
if(element == m.element && rowIndex == m.rowIndex && columnIndex == m.columnIndex)
return true;
else
return false;
}
};
template <class T>
class sparseMatrix
{
template <class U>
friend std::ostream& operator<<(std::ostream &os, sparseMatrix<U> &m);
// Q42
template <class U>
friend std::istream& operator>>(std::istream &is, sparseMatrix<U> &m);
public:
sparseMatrix() {}
// Q43
sparseMatrix(const sparseMatrix<T>& theMatrix);
sparseMatrix(int r, int c) {rows = r; columns = c;}
sparseMatrix<T> transpose();
sparseMatrix<T> add(sparseMatrix<T> &m);
// Q41
T get(int i, int j);
void set(int i, int j, const T& value);
void insert(int i, int j, const T& value);
// Q45
sparseMatrix<T> multiple(sparseMatrix<T>& theMatrix);
private:
int rows, columns; // 矩阵的行数和列数
// 添加元素通过terms的成员函数实现
// 非0项数,用ArrayList装下各个单独的矩阵节点结构体,arrayList是连续空间存储
arrayList<matrixTerm<T>> terms;
};
template <class T>
T sparseMatrix<T>::get(int i, int j)
{
typename arrayList<matrixTerm<T>>::myIterator it = terms.begin();
while (it != terms.end())
{
if (it->rowIndex == i && it->columnIndex == j)
return it->element;
else
it++;
}
return 0;
}
template <class T>
void sparseMatrix<T>::set(int i, int j, const T &value)
{
typename arrayList<matrixTerm<T>>::myIterator it = terms.begin();
while (it != terms.end())
{
if (it->rowIndex == i && it->columnIndex == j)
{
it->element = value;
return;
}
else
it++;
}
if(it == terms.end())
std::cout << "This element should be 0! " << std::endl;
}
template <class T>
void sparseMatrix<T>::insert(int i, int j, const T &value)
{
typename arrayList<matrixTerm<T>>::myIterator it = terms.begin();
matrixTerm<T> item;
item.rowIndex = i;
item.columnIndex = j;
item.element = value;
int cSize = 0;
while (it != terms.end())
{
if (i*columns+j < it->rowIndex*columns+it->columnIndex)
{
terms.insert(cSize, item);
return;
}
else
{
cSize++;
it++;
}
}
// 如果是最后一个就在这里添加
terms.insert(cSize, item);
}
// 关键是计算转置后的先后顺序
// 统计每一列的数据,然后依次插入就可以了
template <class T>
sparseMatrix<T> sparseMatrix<T>::transpose()
{
sparseMatrix<T> m;
m.columns = rows;
m.rows = columns;
m.terms.reSet(terms.size());
// 两个用来计算对应先后位置的数组
int* colSize = new int[columns+1];
int* rowNext = new int[columns+1];
// 搜寻 *this中每一列的项的数目
for (int i=1;i<=columns;i++)
colSize[i] = 0;
for (typename arrayList<matrixTerm<T>>::myIterator it = terms.begin();it != terms.end();it++)
colSize[it->columnIndex]++; // 对应列数的数量加一
// 寻找原数组中每一列的数据起始位置,即转置后每一行的起始点(在转置后线性表中的序号)
rowNext[1] = 0;
for (int i=2;i<=columns;i++)
rowNext[i] = rowNext[i-1] + colSize[i-1];
matrixTerm<T> mTerm;
for (typename arrayList<matrixTerm<T>>::myIterator it = terms.begin();it != terms.end();it++)
{
int j = rowNext[it->columnIndex]++;
mTerm.columnIndex = it->rowIndex;
mTerm.rowIndex = it->columnIndex;
mTerm.element = it->element;
m.terms.set(j, mTerm);
}
return m;
}
template <class T>
sparseMatrix<T> sparseMatrix<T>::add(sparseMatrix<T> &m)
{
sparseMatrix<T> matrixItem;
if (rows != m.rows || columns != m.columns)
{
std::cout << "the shape of two matrix is different! " << std::endl;
return matrixItem;
}
matrixItem.rows = rows;
matrixItem.columns = columns;
int cSize = 0;
typename arrayList<matrixTerm<T>>::myIterator thisIterator = terms.begin();
typename arrayList<matrixTerm<T>>::myIterator thisEnd = terms.end();
typename arrayList<matrixTerm<T>>::myIterator mIterator = m.terms.begin();
typename arrayList<matrixTerm<T>>::myIterator mEnd = m.terms.end();
// 当有一个到达End时就必须退出了,因为他没有数据了,没法进行接下来的判断
while (thisIterator != thisEnd && mIterator != mEnd)
{
int thisIndex = thisIterator->rowIndex * columns + thisIterator->columnIndex;
int mIndex = mIterator->rowIndex * columns + mIterator->columnIndex;
if (thisIndex < mIndex)
{
matrixItem.terms.insert(cSize, *thisIterator);
cSize++;
thisIterator++;
}
else if (thisIndex == mIndex)
{
// 仅当相加和不为零时才加入到线性表中
if (thisIterator->element + mIterator->element != 0)
{
matrixTerm<T> mTerm;
mTerm.rowIndex = thisIterator->rowIndex;
mTerm.columnIndex = thisIterator->columnIndex;
mTerm.element = thisIterator->element + mIterator->element;
matrixItem.terms.insert(cSize, mTerm);
}
cSize++;
thisIterator++;
mIterator++;
}
else
{
matrixItem.terms.insert(cSize, *mIterator);
cSize++;
mIterator++;
}
}
for(;thisIterator != thisEnd; thisIterator++)
matrixItem.terms.insert(cSize++, *thisIterator);
for(;mIterator != mEnd; mIterator++)
matrixItem.terms.insert(cSize++, *mIterator);
return matrixItem;
}
template <class T>
std::ostream& operator<<(std::ostream &os, sparseMatrix<T> &m)
{
os << "rows = " << m.rows << " columns = " << m.columns << std::endl;
os << "nonzero terms = " << m.terms.size() << std::endl;
// 将非零元素逐个输出
for (typename arrayList<matrixTerm<T>>::myIterator it = m.terms.begin();it != m.terms.end();it++)
os << "a(" << it->rowIndex << "," << it->columnIndex << ") = " << it->element << std::endl;
return os;
}
template <class T>
std::istream& operator>>(std::istream &is, sparseMatrix<T> &m)
{
int numberOfTerms;
std::cout << "Enter number of rows, columns, and number of terms. " << std::endl;
is >> m.rows >> m.columns >> numberOfTerms;
// 重新设置m.terms 的大小,用以重新填充数据
matrixTerm<T> mTerm;
std::cout << "Please input from left to right, from up to down." << std::endl;
for(int i=0; i<numberOfTerms;)
{
std::cout << "Enter row, colunm and value of term " << i+1 << std::endl;
is >> mTerm.rowIndex >> mTerm.columnIndex >> mTerm.element;
if (mTerm.rowIndex>m.rows||mTerm.rowIndex<1||mTerm.columnIndex>m.columns||mTerm.columnIndex<1)
{
std::cout << "The Index is out of range!" << std::endl;
continue;
}
else if(mTerm.element == 0)
{
std::cout << "The element = 0, shouldn't be insert in the matrix!" << std::endl;
continue;
}
m.terms.insert(i, mTerm);
i++;
}
return is;
}
template<class T>
sparseMatrix<T>::sparseMatrix(const sparseMatrix<T> &theMatrix)
{
rows = theMatrix.rows;
columns = theMatrix.columns;
terms = theMatrix.terms;
}
template<class T>
sparseMatrix<T> sparseMatrix<T>::multiple(sparseMatrix<T> &theMatrix)
{
sparseMatrix<T> mItem(rows, theMatrix.columns), transMatrix = theMatrix.transpose(); // 转置后相乘更方便
typename arrayList<matrixTerm<T>>::myIterator it = terms.begin();
typename arrayList<matrixTerm<T>>::myIterator itEnd = terms.end();
typename arrayList<matrixTerm<T>>::myIterator mt = transMatrix.terms.begin(), mtNow = mt;
typename arrayList<matrixTerm<T>>::myIterator mtEnd = transMatrix.terms.end();
// 将两个矩阵的每一行都分别描述
arrayList<matrixTerm<T>> *thisBullet, *transBullet;
thisBullet = new arrayList<matrixTerm<T>> [rows+1];
transBullet = new arrayList<matrixTerm<T>> [transMatrix.rows+1];
for (;it!=itEnd;it++)
thisBullet[it->rowIndex].push_back(*it);
for (;mt!=mtEnd;mt++)
transBullet[mt->rowIndex].push_back(*mt);
for (int i=1;i<rows+1;i++) // 遍历左乘矩阵的每一行
{
for (int j=1;j<transMatrix.rows+1;j++) // 遍历右乘矩阵的每一列
{
T sum = 0;
typename arrayList<matrixTerm<T>>::myIterator thisH = thisBullet[i].begin();
typename arrayList<matrixTerm<T>>::myIterator thisEnd = thisBullet[i].end();
typename arrayList<matrixTerm<T>>::myIterator transH = transBullet[j].begin();
typename arrayList<matrixTerm<T>>::myIterator transEnd = transBullet[j].end();
while (thisH != thisEnd && transH != transEnd)
{
if (thisH->columnIndex == transH->columnIndex)
{
sum = sum + thisH->element * transH->element;
thisH++;transH++;
}
else if (thisH->columnIndex < transH->columnIndex)
thisH++;
else
transH++;
}
mItem.insert(i,j,sum);
}
}
return mItem;
}
linkedMatrix类的相关问题
Q51
基类是前一章的,不做任何修改
linkedMatrix.h
#ifndef MAIN_LINKEDMATRIX_H
#define MAIN_LINKEDMATRIX_H
#include "extendedChain.h"
#include "printError.h"
// 这两个结构体要重载一些运算符才能符合extendedChain类的数据要求
template <class T>
struct rowElement
{
int col;
T value;
rowElement() {}
bool operator==(const rowElement<T>& r) const {return (col == r.col && r.value == value);}
bool operator!=(const rowElement<T>& r) const {return !((*this)==r);}
template <class U>
friend std::ostream& operator<<(std::ostream& out, const rowElement<U>& r);
};
template <class U>
std::ostream& operator<<(std::ostream& out, const rowElement<U>& r)
{
out << "col: " << r.col << " value: " << r.value <<std::endl;
return out;
}
template <class T>
struct headerElement
{
int row;
extendedChain<rowElement<T>> rowChain;
headerElement() {};
bool operator==(const headerElement<T>& h) const {return (row == h.row && rowChain == h.rowChain);}
bool operator!=(const headerElement<T>& h) const {return !((*this)==h);}
template <class U>
friend std::ostream& operator<<(std::ostream& out, const headerElement<U>& h);
};
template <class U>
std::ostream& operator<<(std::ostream& out, const headerElement<U>& h)
{
out << "row: " << h.row << " " << h.rowChain << std::endl;
return out;
}
template <class T>
class linkedMatrix
{
template <class U>
friend std::ostream& operator<<(std::ostream& os, const linkedMatrix<U>& m);
public:
linkedMatrix(int rows, int columns) {totalRows = rows; totalCols = columns;}
linkedMatrix<T> transpose();
// Q51(3)
linkedMatrix<T> add(linkedMatrix<T> &m);
// Q51(2)
T get(int i, int j);
void set(int i, int j, const T& value);
// Q51(1)
void insert(int i, int j, const T& value);
// Q51(4)
linkedMatrix<T> minus(linkedMatrix<T> &m);
// Q51(5)
linkedMatrix<T> multiple(linkedMatrix<T> &m);
bool isEmpty() const;
private:
int totalRows, totalCols;
extendedChain<headerElement<T>> headerChain;
};
template<class T>
T linkedMatrix<T>::get(int i, int j)
{
if (i > totalRows || i < 1 || j > totalCols || j < 1)
std::cout <<"The index is out of range!" << std::endl;
typename extendedChain<headerElement<T>>::myIterator ih = headerChain.begin();
typename extendedChain<headerElement<T>>::myIterator ihEnd = headerChain.end();
for (; ih != ihEnd && i >= ih->row; ih++) {
if (i == ih->row)
{
typename extendedChain<rowElement<T>>::myIterator ir = ih->rowChain.begin();
typename extendedChain<rowElement<T>>::myIterator irEnd = ih->rowChain.end();
for (; ir != irEnd && j >= ir->col; ir++)
{
if (j == ir->col)
return ir->value;
}
}
}
return 0;
}
template<class T>
void linkedMatrix<T>::set(int i, int j, const T &value)
{
if(i>totalRows||i<1||j>totalCols||j<1)
{
std::cout << "The index is out of range!" << std::endl;
return;
}
typename extendedChain<headerElement<T>>::myIterator ih = headerChain.begin();
typename extendedChain<headerElement<T>>::myIterator ihEnd = headerChain.end();
for (;ih!=ihEnd && i>=ih->row;ih++)
{
if(i == ih->row)
{
typename extendedChain<rowElement<T>>::myIterator ir = ih->rowChain.begin();
typename extendedChain<rowElement<T>>::myIterator irEnd = ih->rowChain.end();
for(;ir!=irEnd && j>=ir->col;ir++)
{
if(j == ir->col)
{
ir->value = value;
return;
}
}
}
}
std::cout << "The element a(" << i << "," << j << ") should be zero, couldn't set to be " << value << std::endl;
}
template<class T>
void linkedMatrix<T>::insert(int i, int j, const T &value)
{
int headerCount = 0, rowCount = 0;
if(i>totalRows||i<1||j>totalCols||j<1)
{
std::cout << "The index is out of range!" <<std::endl;
return;
}
else if(value==0)
{
std::cout << "The insert value should be zero!" << std::endl;
return;
}
typename extendedChain<headerElement<T>>::myIterator ih = headerChain.begin(), ihHeader = ih;
typename extendedChain<headerElement<T>>::myIterator ihEnd = headerChain.end();
for (;ih!=ihEnd && i>=ih->row;ih++)
{
headerCount++;
rowCount=0;
if(i == ih->row) // 当前元素所在行不为空
{
typename extendedChain<rowElement<T>>::myIterator ir = ih->rowChain.begin(), irHeader = ir;
typename extendedChain<rowElement<T>>::myIterator irEnd = ih->rowChain.end();
for(;ir!=irEnd && j>=ir->col;ir++)
{
rowCount++;
if(j == ir->col) // 插入的元素已经存在
{
std::cout << "The element already exist, can't be insert!" << std::endl;
return;
}
}
rowElement<T> rowItem;
rowItem.col = j; rowItem.value = value;
ih->rowChain.insert(rowCount, rowItem);
return;
}
}
rowElement<T> rowItem;
headerElement<T> headerItem;
rowItem.col = j;rowItem.value = value;
headerItem.row = i;
headerItem.rowChain.push_back(rowItem);
headerChain.insert(headerCount, headerItem);
}
template<class T>
bool linkedMatrix<T>::isEmpty() const
{
if(headerChain.size() == 0)
return true;
else
return false;
}
template <class U>
std::ostream& operator<<(std::ostream& os, const linkedMatrix<U>& m)
{
typename extendedChain<headerElement<U>>::myIterator ih = m.headerChain.begin(), ihHeader = ih;
typename extendedChain<headerElement<U>>::myIterator ihEnd = m.headerChain.end();
for (;ih!=ihEnd;ih++)
{
typename extendedChain<rowElement<U>>::myIterator ir = ih->rowChain.begin(), irHeader = ir;
typename extendedChain<rowElement<U>>::myIterator irEnd = ih->rowChain.end();
for(;ir!=irEnd;ir++)
os << "a(" << ih->row << "," << ir->col << ") = " << ir->value << std::endl;
}
if (m.isEmpty())
os << "All element is zero" << std::endl;
return os;
}
template<class T>
linkedMatrix<T> linkedMatrix<T>::transpose()
{
linkedMatrix<T> mItem(totalCols, totalRows);
typename extendedChain<headerElement<T>>::myIterator ih = headerChain.begin();
typename extendedChain<headerElement<T>>::myIterator ihEnd = headerChain.end();
// 包含行列表的数组
extendedChain<rowElement<T>> *bin;
bin = new extendedChain<rowElement<T>> [totalCols+1];
for (;ih!=ihEnd;ih++)
{
typename extendedChain<rowElement<T>>::myIterator ir = ih->rowChain.begin();
typename extendedChain<rowElement<T>>::myIterator irEnd = ih->rowChain.end();
rowElement<T> x;
x.col = ih->row;
for (;ir!=irEnd;ir++)
{
x.value = ir->value;
bin[ir->col].push_back(x);
}
}
headerElement<T> h;
for(int i=1;i<totalCols+1;i++)
{
if(!bin[i].empty())
{
h.row = i;
h.rowChain = bin[i];
mItem.headerChain.push_back(h);
}
}
delete [] bin;
return mItem;
}
template<class T>
linkedMatrix<T> linkedMatrix<T>::add(linkedMatrix<T> &m)
{
if (totalRows!=m.totalRows || totalCols!=m.totalCols)
{
std::cout << "The shape of two matrixex is different!" << std::endl;
return linkedMatrix<T>(0,0);
}
linkedMatrix<T> mItem(totalRows, totalCols);
typename extendedChain<headerElement<T>>::myIterator ih = headerChain.begin();
typename extendedChain<headerElement<T>>::myIterator ihEnd = headerChain.end();
typename extendedChain<headerElement<T>>::myIterator mh = m.headerChain.begin();
typename extendedChain<headerElement<T>>::myIterator mhEnd = m.headerChain.end();
while (ih != ihEnd && mh != mhEnd)
{
headerElement<T> headerItem;
int ir = ih->row, mr = mh->row;
extendedChain<rowElement<T>> iChain = ih->rowChain, mChain = mh->rowChain;
typename extendedChain<rowElement<T>>::myIterator iRowH = iChain.begin();
typename extendedChain<rowElement<T>>::myIterator iRowHEnd = iChain.end();
typename extendedChain<rowElement<T>>::myIterator mRowH = mChain.begin();
typename extendedChain<rowElement<T>>::myIterator mRowHEnd = mChain.end();
if (ir < mr)
{
headerItem.row = ir;
for (;iRowH!=iRowHEnd;iRowH++)
headerItem.rowChain.push_back(*iRowH);
ih++;
}
else if(ir > mr)
{
headerItem.row = mr;
for (;mRowH!=mRowHEnd;mRowH++)
headerItem.rowChain.push_back(*mRowH);
mh++;
}
else // 同一行
{
rowElement<T> rowItem;
headerItem.row = ir;
while (iRowH!=iRowHEnd && mRowH!=mRowHEnd)
{
int ic = iRowH->col, mc = mRowH->col;
if (ic < mc)
{
rowItem.col = ic;
rowItem.value = iRowH->value;
iRowH++;
}
else if(ic > mc)
{
rowItem.col = mc;
rowItem.value = mRowH->value;
mRowH++;
}
else
{
rowItem.col = ic;
rowItem.value = iRowH->value + mRowH->value;
iRowH++, mRowH++;
}
headerItem.rowChain.push_back(rowItem);
}
for (;iRowH!=iRowHEnd;iRowH++)
{
rowItem.col = iRowH->col;
rowItem.value = iRowH->value;
headerItem.rowChain.push_back(rowItem);
}
for(;mRowH!=mRowHEnd;mRowH++)
{
rowItem.col = mRowH->col;
rowItem.value = mRowH->value;
headerItem.rowChain.push_back(rowItem);
}
ih++,mh++;
}
mItem.headerChain.push_back(headerItem);
}
for (;ih!=ihEnd;ih++)
{
extendedChain<rowElement<T>> iChain = ih->rowChain;
typename extendedChain<rowElement<T>>::myIterator iRowH = iChain.begin();
typename extendedChain<rowElement<T>>::myIterator iRowHEnd = iChain.end();
headerElement<T> headerItem;
headerItem.row = ih->row;
for (;iRowH!=iRowHEnd;iRowH++)
headerItem.rowChain.push_back(*iRowH);
mItem.headerChain.push_back(headerItem);
}
for (;mh!=mhEnd;mh++)
{
extendedChain<rowElement<T>> mChain = mh->rowChain;
typename extendedChain<rowElement<T>>::myIterator mRowH = mChain.begin();
typename extendedChain<rowElement<T>>::myIterator mRowHEnd = mChain.end();
headerElement<T> headerItem;
headerItem.row = mh->row;
for (;mRowH!=mRowHEnd;mRowH++)
headerItem.rowChain.push_back(*mRowH);
mItem.headerChain.push_back((headerItem));
}
return mItem;
}
template<class T>
linkedMatrix<T> linkedMatrix<T>::minus(linkedMatrix<T> &m)
{
if (totalRows!=m.totalRows || totalCols!=m.totalCols)
{
std::cout << "The shape of two matrixex is different!" << std::endl;
return linkedMatrix<T>(0,0);
}
linkedMatrix<T> mItem(totalRows, totalCols);
rowElement<T> rowItem;
typename extendedChain<headerElement<T>>::myIterator ih = headerChain.begin();
typename extendedChain<headerElement<T>>::myIterator ihEnd = headerChain.end();
typename extendedChain<headerElement<T>>::myIterator mh = m.headerChain.begin();
typename extendedChain<headerElement<T>>::myIterator mhEnd = m.headerChain.end();
while (ih != ihEnd && mh != mhEnd)
{
headerElement<T> headerItem;
int ir = ih->row, mr = mh->row;
extendedChain<rowElement<T>> iChain = ih->rowChain, mChain = mh->rowChain;
typename extendedChain<rowElement<T>>::myIterator iRowH = iChain.begin();
typename extendedChain<rowElement<T>>::myIterator iRowHEnd = iChain.end();
typename extendedChain<rowElement<T>>::myIterator mRowH = mChain.begin();
typename extendedChain<rowElement<T>>::myIterator mRowHEnd = mChain.end();
if (ir < mr)
{
headerItem.row = ir;
for (;iRowH!=iRowHEnd;iRowH++)
headerItem.rowChain.push_back(*iRowH);
ih++;
}
else if(ir > mr)
{
headerItem.row = mr;
for (;mRowH!=mRowHEnd;mRowH++)
{
rowItem.col = mRowH->col;
rowItem.value = -mRowH->value;
headerItem.rowChain.push_back(rowItem);
}
mh++;
}
else // 同一行
{
// rowElement<T> rowItem;
headerItem.row = ir;
while (iRowH!=iRowHEnd && mRowH!=mRowHEnd)
{
int ic = iRowH->col, mc = mRowH->col;
if (ic < mc)
{
rowItem.col = ic;
rowItem.value = iRowH->value;
iRowH++;
}
else if(ic > mc)
{
rowItem.col = mc;
rowItem.value = -mRowH->value;
mRowH++;
}
else
{
rowItem.col = ic;
rowItem.value = iRowH->value - mRowH->value;
iRowH++, mRowH++;
}
headerItem.rowChain.push_back(rowItem);
}
for (;iRowH!=iRowHEnd;iRowH++)
{
rowItem.col = iRowH->col;
rowItem.value = iRowH->value;
headerItem.rowChain.push_back(rowItem);
}
for(;mRowH!=mRowHEnd;mRowH++)
{
rowItem.col = mRowH->col;
rowItem.value = -mRowH->value;
headerItem.rowChain.push_back(rowItem);
}
ih++,mh++;
}
mItem.headerChain.push_back(headerItem);
}
for (;ih!=ihEnd;ih++)
{
extendedChain<rowElement<T>> iChain = ih->rowChain;
typename extendedChain<rowElement<T>>::myIterator iRowH = iChain.begin();
typename extendedChain<rowElement<T>>::myIterator iRowHEnd = iChain.end();
headerElement<T> headerItem;
headerItem.row = ih->row;
for (;iRowH!=iRowHEnd;iRowH++)
headerItem.rowChain.push_back(*iRowH);
mItem.headerChain.push_back(headerItem);
}
for (;mh!=mhEnd;mh++)
{
extendedChain<rowElement<T>> mChain = mh->rowChain;
typename extendedChain<rowElement<T>>::myIterator mRowH = mChain.begin();
typename extendedChain<rowElement<T>>::myIterator mRowHEnd = mChain.end();
headerElement<T> headerItem;
headerItem.row = mh->row;
for (;mRowH!=mRowHEnd;mRowH++)
{
rowItem.col = mRowH->col;
rowItem.value = -mRowH->value;
headerItem.rowChain.push_back(rowItem);
}
mItem.headerChain.push_back((headerItem));
}
return mItem;
}
template<class T>
linkedMatrix<T> linkedMatrix<T>::multiple(linkedMatrix<T> &m)
{
if (totalCols!=m.totalRows)
{
std::cout << "THe column of first matrix and row of second matrix are different!" << std::endl;
return linkedMatrix<T>(0, 0);
}
linkedMatrix<T> mItem(totalRows, m.totalCols), transMatrix(m.totalCols, m.totalRows);
transMatrix = m.transpose();
if (isEmpty() || m.isEmpty()) // 如果有一个矩阵全为0,可以直接返回
return mItem;
// 转置之后可以很方便的访问原来的第二个矩阵的列,即转置后第二个矩阵的行
typename extendedChain<headerElement<T>>::myIterator ih = headerChain.begin();
typename extendedChain<headerElement<T>>::myIterator ihEnd = headerChain.end();
while (ih!=ihEnd)
{
int Ir=0,Ic=0;
typename extendedChain<headerElement<T>>::myIterator mh = transMatrix.headerChain.begin();
typename extendedChain<headerElement<T>>::myIterator mhEnd = transMatrix.headerChain.end();
while (mh!=mhEnd)
{
Ir = ih->row, Ic = mh->row;
T sum=0;
typename extendedChain<rowElement<T>>::myIterator iRowH = ih->rowChain.begin();
typename extendedChain<rowElement<T>>::myIterator iRowEnd = ih->rowChain.end();
typename extendedChain<rowElement<T>>::myIterator mRowH = mh->rowChain.begin();
typename extendedChain<rowElement<T>>::myIterator mRowEnd = mh->rowChain.end();
while (iRowH!=iRowEnd && mRowH!=mRowEnd)
{
if (iRowH->col == mRowH->col)
{
sum = sum + iRowH->value * mRowH->value;
iRowH++;mRowH++;
}
else if (iRowH->col < mRowH->col)
iRowH++;
else
mRowH++;
}
mh++;
mItem.insert(Ir, Ic, sum);
}
ih++;
}
return mItem;
}
#endif //MAIN_LINKEDMATRIX_H