数据结构、算法与应用 C++语言描述 第7章习题

本文介绍了C++中矩阵类的实现,包括矩阵的增删改查操作,以及矩阵的加减乘运算。同时,讨论了稀疏矩阵类的实现,包括使用链表存储非零元素,以及矩阵转置、加法和乘法运算。代码中定义了友元函数以支持输入输出操作,并处理了不同形状矩阵间的运算错误。此外,还涉及了矩阵元素的存储结构,如ArrayList和extendedChain,以及如何处理这些结构的内存管理和数据访问。
摘要由CSDN通过智能技术生成


这一章的问题有很多重复性问题,选择了其中比较常用的一些问题进行了实现。

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都需要有==、<<等操作。所以有两种方法解决这个问题的方法:

  1. 删除这些类型中可能需要这些操作的函数
  2. 在这些基本数据类型中添加这些操作
    下面的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
  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值