和我一起写矩阵类(一)
和我一起寫矩陣類(一)
?
?
?
?
?
?
?
?
?
?
?
大連理工大學軟件學院WAKU(轉(zhuǎn)載請保留署名)
最近Mr.Zeng的一個作業(yè)就是自己實現(xiàn)一個矩陣類,這是一個非常有實用價值的類。我花了幾天完成了,期間也增長了很多知識,不敢獨享,拿出來和大家共同學習。由于本人水平很非常有限,有錯誤不要給我面子,請盡快指出,我將不勝感激!!
開始吧。
矩陣也是一種數(shù)據(jù)結(jié)構(gòu),所以在設計之前一定要明確有哪些數(shù)據(jù)和哪些操作。首先,最容易想到的,矩陣要有一個一個二維數(shù)組,好這簡單:
double array[3][3];
?
?
?
?
?
?
?
先等一下,為什么是double類型的?為什么是3x3的二維數(shù)組,如果圖省事,這么定義當然可以,而且在相當一部分場合中,這個矩陣類也很實用。
我們要有更高的追求,要想辦法使我們的類壽命更長。改進它:
類型用模板,可以花最少的時間最大程度上的提高代碼的重用性。
?
?
?
?
?
?
?
template?<class?T>
?
?
?
?
?
?
?
那么二維數(shù)組應該幾乘幾的呢,答案是由用戶確定。數(shù)組在矩陣使用的時候動態(tài)創(chuàng)建,可大可小,最具有靈活性。那么動態(tài)的二維數(shù)組應如何表示呢?大家都動態(tài)創(chuàng)建過一維數(shù)組,寫過類似這樣的語句:
int *p = new int[10];
?
?
?
?
?
?
?
new關(guān)鍵字動態(tài)的申請了10個int類型的連續(xù)空間,并把這段連續(xù)空間的首地址賦給指針p。然后就可以使用p[i]來引用數(shù)組元素,因為數(shù)組名就是指針。以此類推,動態(tài)二維數(shù)組也應該用指針來表示、來引用元素。在定義指針之前,還是回顧一下二維數(shù)組的一些概念,舉例說明:
double array[3][3];
?
?
?
?
?
?
?
定義了3x3的double型數(shù)組,由于內(nèi)存是線性的,所以這9個元素在內(nèi)存中都是“一條直線”似的存放。array[0][0]是頭一個元素,array[2][2]是最后一個元素,這很好理解。那么array[0]代表什么?它是什么東西?
?
?
?
?
?
?
?
它其實也是個指針,指向數(shù)組的第一行元素的行首。同理array[1]是第二行行首指針,array[2]是第三行。array呢?它是數(shù)組名,那肯定也是個指針,但是它可不是我們常用的那種指針,而是一個指向指針的指針(二級指針)。它指向的是“指向第一行行首的指針”。看著像一個繞口令,仔細琢磨一下就明白了。如果你感興趣,輸入以下代碼并執(zhí)行:
double array[3][3];
?
?
?
?
?
?
?
cout<<&array[0]<<endl <<array<<endl;
?
?
?
?
?
?
?
你會發(fā)現(xiàn)輸出的值是完全相同的,這就證明了array指向了array[0]。總結(jié)一下就是:
想表示或引用幾維數(shù)組,就需要幾級指針。
?
?
?
?
?
?
?
那么我們的類屬性的聲明就差不多了:
template <class T>
?
?
?
?
?
?
?
class CMatrix
?
?
?
?
?
?
?
{
?
?
?
?
?
?
?
??? int m;???? //行數(shù)
?
?
?
?
?
?
?
??? int n;???? //列數(shù)
?
?
?
?
?
?
?
??? T** p;???? //二維數(shù)組指針
?
?
?
?
?
?
?
};
?
?
?
?
?
?
?
由于是動態(tài)創(chuàng)建的數(shù)組,所以矩陣的行和列各需要用一個int型變量來記錄。p就是用模板創(chuàng)建的二級指針,來表示二維數(shù)組。
下一次我們就開始類方法的設計。大家覺得我寫的還可以,麻煩貴手輕抬回一下貼,讓我知道有人在看,好有動力寫下去,謝謝~~
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?和我一起寫矩陣類(二)
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
上次說到了在構(gòu)造函數(shù)和SetMatrix函數(shù)中用數(shù)組給矩陣賦值,兩個函數(shù)的第三個形參都是T* array。用這種方式傳遞二維數(shù)組應該說有點無奈,我們以前學過的傳遞二維數(shù)組都是類似以下形式:
?
?
?
void function(int a[][10]);
?
?
?
數(shù)組的最高維一定要是一個常數(shù),但是我們的矩陣的大小是不定的,不能確定各個維的大小,那怎么辦?不要忘了,所有數(shù)組在內(nèi)存中都是線性的,我們可以用一個一級指針來引用任意維的數(shù)組。看以下示例代碼:
?
?
?
void main()
?
?
?
{
?
?
?
??? int a[3][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
?
?
?
??? int *p = (int*)a;
?
??? cout<<p[3]<<endl;?
?
?
}
?
?
?
程序工作良好,并如你所愿,輸出了4。這就說明一級指針也是可以引用二維數(shù)組的。如果我想用指針p引用原數(shù)組里的元素a[1][1]就需要做一個簡單的變換p[1*3 + 1] 即p[4],這就是為什么給p[i][j]賦值的時候用array[i*n + j]了。n即為二維數(shù)組的列數(shù)。
?
?
?
但是和上面示例的第二條語句一樣,構(gòu)造函數(shù)CMatrix(int m, int n, T* array)和SetMatrix(int m, int n, T* array)函數(shù)在調(diào)用的時候都需要把二維數(shù)組的數(shù)組名強制轉(zhuǎn)換成一級指針。調(diào)用形式如下:
?
?
?
double array[2][2] = {1, 2, 3, 4};
?
?
?
CMatrix<double>?? matrix(2, 2, (double*)array);
?
?
?
或者
?
?
?
double array[2][2] = {1, 2, 3, 4};
?
?
?
CMatrix<double>?? matrix;
?
?
?
matrix.SetMatrix(2, 2, (double*)array);
?
?
?
這樣就定義了一個2行2列名為matrix的矩陣對象,并且矩陣里面的值和二維數(shù)組array一樣。
?
?
?
下面我們完成最后一個SetMatrix函數(shù),在用構(gòu)造函數(shù)CMatrix(int m, int n)創(chuàng)建對象后,如果只想用一個數(shù)組填充矩陣而不改變行列值,就可以用下面的函數(shù):
?
?
?
template <class T>
?
?
?
void CMatrix<T>::SetMatrix(T* array)
?
?
?
{
?
?
?
??? int i, j;
?
??? if (p)?
?
?
??? {
?
?
?
?????? for (i = 0; i < this->m; i++)
?
?
?
?????? {
?
?
?
?????????? delete[] p[i];
?
?
?
?????? }
?
?
?
?????? delete[] p;
?
?
?
??? }
?
?
?
?
?
?
??? for (i = 0; i < m; i++)
?
?
?
??? {
?
?
?
?????? for (j = 0; j < n; j++)
?
?
?
?????? {
?
?
?
?????????? p[i][j] = array[i*n+j];
?
?
?
?????? }
?
?
?
}
?
?
?
}
?
?
?
沒什么新東西就不詳細講解了。
?
?
?
至此,矩陣創(chuàng)建和初始化的相關(guān)函數(shù)基本上都已經(jīng)完成了,如果你勤快,你的類聲明應該是這個樣子的:
?
?
?
template <class T>
?
?
?
class CMatrix
?
?
?
{
?
?
?
??? int m;???? //行數(shù)
?
?
?
??? int n;???? //列數(shù)
?
?
?
??? T** p;???? //二維數(shù)組指針
?
?
?
public:
?
?
?
??? CMatrix(void);
?
?
?
??? CMatrix(int m, int n);?????????
?
?
?
??? CMatrix(int m, int n, T* array);
?
?
?
??? ~CMatrix(void);
?
?
?
??? void SetMatrix(int m, int n);
?
?
?
??? void SetMatrix(int m, int n, T* array);
?
?
?
??? void SetMatrix(T* array);
?
?
?
};
?
?
?
怎么樣?大家還能跟上吧?有什么問題盡管問,我能答的肯定會回答。下次我們開始寫矩陣運算的函數(shù),并對我做的時候遇到的問題進行詳細討論。敬請期待~
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
和我一起寫矩陣類(三)
?
?
?
大連理工大學軟件學院WAKU(轉(zhuǎn)載請保留署名)
?
?
?
?
?
?
類的方法(也可叫做成員函數(shù))從構(gòu)造函數(shù)開始,我寫的一個構(gòu)造函數(shù)是這樣的:
template <class T>
?
?
?
?
?
?
?
CMatrix<T>::CMatrix(void)
?
?
?
?
?
?
?
{
?
?
?
?
?
?
?
??? m = 0; n? = 0;
?
?
?
?
?
?
?
??? p = NULL;
?
?
?
?
?
?
?
}
?
?
?
?
?
?
?
由于使用了模板,所以在每個成員函數(shù)之前都要加上template <class T>,而且類名后一定要加上<T>,否則會編譯出錯。這是一個無參的構(gòu)造函數(shù),里面把行列值賦0,把數(shù)組的指針置為空,這是一個好習慣。除了安全帶來的另一個好處是避免了定義對象數(shù)組時寫出一長串的初始化表。
?
?
?
?
?
?
?
如果有可能定義類的對象數(shù)組,最好提供類的無參構(gòu)造函數(shù)
?
?
?
?
?
?
?
然后再提供另外的成員函數(shù)完成有參構(gòu)造函數(shù)所完成的功能。我寫的一個有參構(gòu)造函數(shù)是:
?
?
?
?
?
?
?
template <class T>
?
?
?
?
?
?
?
CMatrix<T>::CMatrix(int m, int n)
?
?
?
?
?
?
?
{
?
?
?
?
?
?
?
??? int i, j;
?
??? p = new T*[m];?
?
?
?
?
?
?
??? for (i = 0; i < m; i++)
?
?
?
?
?
?
?
??? {
?
?
?
?
?
?
?
?????? p[i] = new T[n];
?
?
?
?
?
?
?
?????? for (j = 0; j < n; j++)
?
?
?
?
?
?
?
?????? {
?
?
?
?
?
?
?
?????????? p[i][j] = 0;
?
?
?
?
?
?
?
?????? }
?
?
?
?
?
?
?
??? }
?
?
?
?
?
?
?
??? this->m = m; this->n = n;
?
?
?
?
?
?
?
}
?
?
?
?
?
?
?
這是有參構(gòu)造函數(shù)所完成的功能,無參構(gòu)造函數(shù)由于不知道行列的具體值所以不能加入以上代碼,所以我們必須要另寫一個一模一樣的函數(shù)“補充”這個功能:
?
?
?
?
?
?
?
template <class T>
?
?
?
?
?
?
?
void CMatrix<T>::SetMatrix(int m, int n)
?
?
?
?
?
?
?
{
?
?
?
?
?
?
?
??? int i, j;
?
??? p = new T*[m];?
?
?
?
?
?
?
??? for (i = 0; i < m; i++)
?
?
?
?
?
?
?
??? {
?
?
?
?
?
?
?
?????? p[i] = new T[n];
?
?
?
?
?
?
?
?????? for (j = 0; j < n; j++)
?
?
?
?
?
?
?
?????? {
?
?
?
?
?
?
?
?????????? p[i][j] = 0;
?
?
?
?
?
?
?
?????? }
?
?
?
?
?
?
?
??? }
?
?
?
?
?
?
?
??? this->m = m; this->n = n;
?
?
?
?
?
?
?
}??
?
這兩段代碼實現(xiàn)了動態(tài)創(chuàng)建 m 行 n 列二維數(shù)組的功能。 p = new T*[m]; 語句和第一篇里創(chuàng)建一維數(shù)組的語句非常類似,這里申請了有 m 個 T 類型的指針數(shù)組(即數(shù)組里存放的全是指向 T 類型的指針),并把這個數(shù)組的首地址賦給了 p 。然后外層 for 循環(huán)遍歷數(shù)組里的每一個指針,并用每個指針 p[i] 接收由 new 創(chuàng)建的 n 個 T 類型數(shù)組。?
?
?
?
?
?
?
明白前面我講過二維數(shù)組,這段代碼也就很好理解,p[i]是一個行指針,p[0]相當于double array[3][3]里的array[0]、p[1]就相當于array[1];然后每個行指針又“管轄”著剛申請的n個元素。里層for循環(huán)把這一行的元素值初始為0。其實說穿了也很簡單吧。
?
?
?
?
?
?
?
下面把析構(gòu)函數(shù)完成,很簡單,就是釋放申請的空間:
?
?
?
?
?
?
?
template <class T>
?
?
?
?
?
?
?
CMatrix<T>::~CMatrix(void)
?
?
?
?
?
?
?
{
?
?
?
?
?
?
?
??? int i;????
?
?
?
?
?
?
?
??? if (p)
?
?
?
?
?
?
?
??? {
?
?
?
?
?
?
?
?????? for (i = 0; i < m; i++)
?
?
?
?
?
?
?
?????? {
?
?
?
?
?
?
?
?????????? delete[] p[i];
?
?
?
?
?
?
?
?????? }
?
?
?
?
?
?
?
?????? delete[] p;
?
?
?
?
?
?
?
??? }
?
?
?
?
?
?
?
}
?
?
?
?
?
?
?
記住一點,有幾個new就要有幾個delete。另外注意一點,delete后面的[]一定不要落下,否則編譯器并不會報錯,你的內(nèi)存卻還照樣泄漏。
矩陣里面有一個二維數(shù)組,那么一個可以把二維數(shù)組填充到到矩陣里的函數(shù)無疑是非常有用的。讓我們實現(xiàn)它吧:
template <class T>
?
?
?
?
?
?
?
CMatrix<T>::CMatrix(int m, int n, T* array)
?
?
?
?
?
?
?
{
?
?
?
?
?
?
?
??? int i, j;??
?
??? p = new T*[m];?
?
?
?
?
?
?
??? for (i = 0; i < m; i++)
?
?
?
?
?
?
?
??? {
?
?
?
?
?
?
?
?????? p[i] = new T[n];
?
?
?
?
?
?
?
?????? for (j = 0; j < n; j++)
?
?
?
?
?
?
?
?????? {
?
?
?
?
?
?
?
?????????? p[i][j] = array[i*n+j];
?
?
?
?
?
?
?
?????? }
?
?
?
?
?
?
?
??? }
?
?
?
?
?
?
?
??? this->m = m; this->n = n;
?
?
?
?
?
?
?
}
?
?
?
?
?
?
?
這是一個構(gòu)造函數(shù),用于在創(chuàng)建對象時就用二維數(shù)組賦值,對應重載的SetMatrix函數(shù)如下:
?
?
?
?
?
?
?
template <class T>
?
?
?
?
?
?
?
void CMatrix<T>::SetMatrix(int m, int n, T* array)
?
?
?
?
?
?
?
{
?
?
?
?
?
?
?
??? int i, j;
?
??? if (p)?
?
?
?
?
?
?
??? {
?
?
?
?
?
?
?
?????? for (i = 0; i < this->m; i++)
?
?
?
?
?
?
?
?????? {
?
?
?
?
?
?
?
?????????? delete[] p[i];
?
?
?
?
?
?
?
?????? }
?
?
?
?
?
?
?
?????? delete[] p;
?
?
?
?
?
?
?
??? }??
?
??? p = new T*[m];?
?
?
?
?
?
?
??? for (i = 0; i < m; i++)
?
?
?
?
?
?
?
??? {
?
?
?
?
?
?
?
?????? p[i] = new T[n];
?
?
?
?
?
?
?
?????? for (j = 0; j < n; j++)
?
?
?
?
?
?
?
?????? {
?
?
?
?
?
?
?
?????????? p[i][j] = array[i*n+j];
?
?
?
?
?
?
?
?????? }
?
?
?
?
?
?
?
??? }
?
?
?
?
?
?
?
??? this->m = m; this->n = n;
?
?
?
?
?
?
?
}
?
?
?
?
?
?
?
由于調(diào)用SetMatrix函數(shù)時的對象有可能已經(jīng)申請了空間,所以再數(shù)組賦值之前應該釋放掉。
?
?
?
?
?
?
?
我們不是要傳遞二維數(shù)組嗎?為什么第三個參數(shù)是T* array?這不是一個一級指針嗎?不覺得賦值的時候用p[i][j] = array[i*n+j];這種語句很奇怪嗎?請聽下回分解
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的和我一起写矩阵类(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: doll走廊怎么过
- 下一篇: 有哪些游戏手机(汉典有字的基本解释)