数据结构七:矩阵

1. 矩阵的定义

矩阵可以描述为一个二元数组,矩阵的下标通常从1开始。下面是利用上节提到的行优先映射的方法来对矩阵进行实现。

1.1 矩阵的实现

#pragma once

#include 
//矩阵类
template<typename elemType>
class Matirx
{
protected:
    //矩阵的数据成员
    elemType* elems;//存储矩阵元素
    int rows, cols;//矩阵的行和列
private:
    //抽象数据类型及重载编译系统的默认方法声明
    Matirx(int rs, int cs);//构造函数
    ~Matirx();//析构函数
    int getRows() const;//返回矩阵的行数
    int getCols() const;//返回矩阵的列数

    elemType& operator()(int i, int j);
    Matirx(const Matirx & copy);
    Matirx& operator=(const Matirx & copy);
};


template<typename elemType>
Matirx::Matirx(int rs, int cs)
{
    if ( rs > 0 && cs > 0)
    {
        elems = new elemType[rs * cs];
        rows = rs;
        cols = cs;
    }
    else
    {
        std::cout << "行数或列数无效!" << std::endl;
    }
}

template<typename elemType>
Matirx::~Matirx()
{
    if (elems != NULL) delete []elems;
}


template<typename elemType>
int Matirx::getRows() const
{
    return rows;
}

template<typename elemType>
int  Matirx::getCols() const
{
    return cols;
}


template<typename elemType>
elemType&  Matirx::operator()(int i, int j)
{
    if (i < 1 || i > rows || j < 1 || j > cols)
    {
        std::cout << "下标越界!" << std::endl;
    }
    else
    {
        return elems[(i-1)*cols + j - 1]
    }
}

template<typename elemType>
Matirx::Matirx(const Matirx & copy)
{
    rows = copy.rows;
    cols = copy.cols;
    elems = new elemType[rows * cols];
    for (int i = 0; i < rows*cols; i++)
    {
        elems[i] = copy.elems[i];
    }
}


template<typename elemType>
Matirx& Matirx::operator=(const Matirx & copy)
{
    if (© != this)
    {
        if (elems != NULL) delete[]elems;

        rows = copy.rows;
        cols = copy.cols;
        elems = new elemType[rows * cols];
        for (int i = 0; i < rows*cols; i++)
        {
            elems[i] = copy.elems[i];
        }
    }
}

2.特殊矩阵

如果值相同元素或者零元素在矩阵中按一定的规律分布,这样的矩阵称为特殊矩阵
下面介绍一些基本概念:
方阵:行数和列数相同矩阵,下面介绍的矩阵都是特殊矩阵。
对称矩阵:对于对称阵,对于所有的 i i j j a(i,j)=a(j,i) a ( i , j ) = a ( j , i ) .
三对角阵:当 |ij|>0 | i − j | > 0 时有 a(i,j)=0 a ( i , j ) = 0 (或为常数c)。
下三角阵:当 i<j i < j 时有 a(i,j)=0 a ( i , j ) = 0 (或为常数c)。
上三角阵:当 i>j i > j 时有 a(i,j)=0 a ( i , j ) = 0 (或为常数c)。
数据结构七:矩阵_第1张图片

2.1 三对角矩阵

n×n n × n 的矩阵中,三条对角线之外的元素为0或者为常数c。
主对角线: 主对角线上的元素行列坐标满足 i=j i = j .
低对角线:主对角线之下的对角线,其上的元素行列坐标满足 i=j+1 i = j + 1
高对角线:主对角线之上的对角线,其上的元素行列坐标满足 i=j1 i = j − 1
主对角线上有n个元素,两个次对角线上有n-1个元素,所以这三条对角线上有3n-2个元素,加上其他位置的元素都是常数c,因此共需要3n-1个存储单元来存储。现在关键要做的是如何把这含有3n-1个元素的一维数组与矩阵的行列下标建立映射关系。
这里就有三种不同的映射方式:
(1)将常量c放到elems[0]的位置,其他元素按照行优先的方式映射到数组elems中。
(2)将常量c放到elems[0]的位置,其他元素按照先高对角线再主对角线最后低对角线方式映射到数组elems中。
(3)将常量c放到elems[0]的位置,其他元素按照列优先的方式映射到数组elems中。
实际应用中可以自行选择。
下面的实现采用的是方式二。

//三对角矩阵类
template<typename elemType>
class TriDiagonalMatrix
{
protected:
    //成员变量
    elemType* elems;//存储矩阵元素
    int n;//矩阵阶数

private:
    TriDiagonalMatrix(int sz);//构造阶数为sz的三对角阵
    ~TriDiagonalMatrix();//析构函数
    int getSize() const;//获取矩阵的阶数
    elemType& operator()(int i, int j);//重载函数运算符
    TriDiagonalMatrix(const TriDiagonalMatrix& copy);//复制构造函数
    TriDiagonalMatrix& operator=(const TriDiagonalMatrix ©);
};

template<typename elemType>
TriDiagonalMatrix::TriDiagonalMatrix(int sz)
{
    if (sz < 1)
    {
        std::cout << "矩阵阶数不能小于1!" << std::endl;
    }
    else
    {
        n = sz;
        elems = new elemType[3 * n - 1];
    }

}

template<typename elemType>
TriDiagonalMatrix::~TriDiagonalMatrix()
{
    if (elems != NULL) delete []elems;
}


template<typename elemType>
int TriDiagonalMatrix::getSize() const
{
    return n;
}


template<typename elemType>
elemType& TriDiagonalMatrix::operator()(int i, int j)
{
    if (i<1 || i>n || j<1 || j>n)
    {
        std::cout << "下标出界!" << std::endl;
    }
    else
    {
        if (i == j - 1) return elems[i];//高对角线元素
        else if (i == j) return elems[n + i - 1];//i才从1开始,主对角线
        else if (i == j - 1) return elems[2 * n + i - 2];
        else return elems[0];
    }
}


template<typename elemType>
TriDiagonalMatrix::TriDiagonalMatrix
(const TriDiagonalMatrix& copy)
{
    n = copy.n;
    elems = new elemType[3 * n - 1];
    for (int i = 0; i < 3 * n - 1; i++)
    {
        elems[i] = copy.elems[i];
    }
}


template<typename elemType>
TriDiagonalMatrix& TriDiagonalMatrix::operator=
(const TriDiagonalMatrix ©)
{
    if (© != this)
    {
        if (elems != NULL) delete[]elems;

        n = copy.n;
        elems = new elemType[3 * n - 1];
        for (int i = 0; i < 3 * n - 1; i++)
        {
            elems[i] = copy.elems[i];
        }
    }
}

2.2 三角矩阵

三角矩阵的非常数的元素的个数为:

n(n+1)2 n ( n + 1 ) 2

所以共需要要
n(n+1)2+1 n ( n + 1 ) 2 + 1

个存储单元,一般将常数存储在elems[0].
接下来采用行优先映射,来看看各类三角矩阵的映射关系。
(1)对于下三角矩阵
a(i,j) a ( i , j ) 在一维数组中的位置为:
i(i1)2+j i ( i − 1 ) 2 + j

(2)对于上三角,我们采用列优先的方式,这样映射关系与上面是一样的。
(3)对于对称矩阵,采用行优先的方式:
a(i,j)在elems中的位子为:
{i(i1)2+j1,ijj(j1)2+i1,i<j { i ( i − 1 ) 2 + j − 1 , i ≥ j j ( j − 1 ) 2 + i − 1 , i < j

你可能感兴趣的:(数据结构)