1. 程式人生 > >資料結構七:矩陣

資料結構七:矩陣

1. 矩陣的定義

矩陣可以描述為一個二元陣列,矩陣的下標通常從1開始。下面是利用上節提到的行優先對映的方法來對矩陣進行實現。

1.1 矩陣的實現

#pragma once

#include <iostream>
//矩陣類
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<elemType> & copy); Matirx<elemType>& operator=(const Matirx<elemType> & copy); }; template<typename
elemType> Matirx<elemType>::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<elemType>::~Matirx() { if
(elems != NULL) delete []elems; } template<typename elemType> int Matirx<elemType>::getRows() const { return rows; } template<typename elemType> int Matirx<elemType>::getCols() const { return cols; } template<typename elemType> elemType& Matirx<elemType>::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<elemType>::Matirx(const Matirx<elemType> & 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<elemType>& Matirx<elemType>::operator=(const Matirx<elemType> & copy) { if (&copy != 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 j a ( i , j ) = a ( j , i ) .
三對角陣:當 | i j | > 0 時有 a ( i , j ) = 0 (或為常數c)。
下三角陣:當 i < j 時有 a ( i , j ) = 0 (或為常數c)。
上三角陣:當 i > j 時有 a ( i , j ) = 0 (或為常數c)。
這裡寫圖片描述

2.1 三對角矩陣

n × n 的矩陣中,三條對角線之外的元素為0或者為常數c。
主對角線: 主對角線上的元素行列座標滿足 i = j .
低對角線:主對角線之下的對角線,其上的元素行列座標滿足 i = j + 1
高對角線:主對角線之上的對角線,其上的元素行列座標滿足 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<elemType>& copy);//複製建構函式
    TriDiagonalMatrix<elemType>& operator=(const TriDiagonalMatrix<elemType> &copy);
};

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

}

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


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


template<typename elemType>
elemType& TriDiagonalMatrix<elemType>::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<elemType>::TriDiagonalMatrix
(const TriDiagonalMatrix<elemType>& 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<elemType>& TriDiagonalMatrix<elemType>::operator=
(const TriDiagonalMatrix<elemType> &copy)
{
    if (&copy != 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 + 1
個儲存單元,一般將常數儲存在elems[0].
接下來採用行優先對映,來看看各類三角矩陣的對映關係。
(1)對於下三角矩陣
a ( i , j ) 在一維陣列中的位置為:
i ( i 1 ) 2 + j
(2)對於上三角,我們採用列優先的方式,這樣對映關係與上面是一樣的。
(3)對於對稱矩陣,採用行優先的方式:
a(i,j)在elems中的位子為:
{ i ( i 1 ) 2 + j 1 , i j j ( j 1 ) 2 + i 1 , i < j