C實現(xiàn)矩陣數(shù)據(jù)結(jié)構(gòu)與計算

用C實現(xiàn)矩陣寫的不像前面的鏈表等數(shù)據(jù)結(jié)構(gòu)寫的順利,因為矩陣里面的內(nèi)容多的多嚣艇,特別是計算部分承冰,著實花了幾天時間。目前還有一小部分算法還沒有實現(xiàn)食零,后續(xù)會補上困乒。
github源碼 文件夾為Matrix,主要有兩個文件:Matrix.c 贰谣、Matrix.h

矩陣的數(shù)據(jù)結(jié)構(gòu)的設(shè)計

矩陣是存儲的一組或多組數(shù)據(jù)娜搂,所以毫無疑問,應(yīng)使用順序存儲的方式存儲數(shù)據(jù)元素吱抚。矩陣最直觀的表示方式是用多維數(shù)組來表示百宇,缺點在于不夠活型酥,使用前必須確定其長度乌企,而且維度變換時十分麻煩。綜合了諸多因素瓢对,我設(shè)計如下的主要使用堆的動態(tài)的矩陣數(shù)據(jù)結(jié)構(gòu):

typedef struct Dshape{
    int shape[4]; //最多四維
}Dshape;

typedef struct Matrix{
    double *array;  
    Dshape dshape; //數(shù)組結(jié)構(gòu)
    int length; //長度
    int size; //空間大小
}Matrix;

我們看結(jié)構(gòu)體Matrix憋肖,里面首先是一個double型的指針*array因痛,這用于指向的矩陣元素存儲塊的首地址。在剛開始的設(shè)計版本中岸更,我把指針的類型設(shè)置為void型鸵膏,這樣*array可以指向任何類型的數(shù)據(jù)塊,但是在存取時需要類型判斷和轉(zhuǎn)換怎炊,比較麻煩谭企,而且在后面矩陣的一些算法如求行列式等就更為麻煩,所以最終設(shè)定Matrix的元素類型為double型评肆。
Dshape dshape定義了矩陣的結(jié)構(gòu)债查,可以看到struct Dshape里定義的是一個int型的大小為4的數(shù)組,這個數(shù)組用來存儲矩陣的結(jié)構(gòu)信息瓜挽,4個int型代表維數(shù)盹廷,最多支持4維。例如久橙,一個2X2(二行二列)的二維矩陣的dshape為{0俄占,0,2淆衷,2}缸榄。要注意的是一個設(shè)定:一維矩陣,即只有一行祝拯,假設(shè)這一行的元素有3個甚带,那么該一維矩陣的dshape為{0,0,0欲低,3}辕宏,而不是{0畜晰,0砾莱,1,3}凄鼻。還有一種情況腊瑟,一列元素,假設(shè)有n個块蚌,那么闰非,該列的dshape為{0,0峭范,n财松,1}。把int型數(shù)組用struct包裝一下纱控,這是一個小技巧辆毡,好處是struct可以直接整體賦值,在代碼中就會簡潔一些甜害,不必再用循環(huán)依次對數(shù)組賦值舶掖。存放多維矩陣元素只用一塊連續(xù)的存儲區(qū)域,而矩陣的結(jié)構(gòu)由dshape來決定尔店,最大的好處在于眨攘,更改數(shù)組的維數(shù)、結(jié)構(gòu)非常的容易嚣州,不需要改矩陣元素的存儲區(qū)域鲫售,只要改一下dshape的值就可以了。
int length保存了矩陣*array里數(shù)據(jù)元素的長度该肴, int size則保存了矩陣*array所占空間的大小情竹。大部分情況下,這兩個值是相等的沙庐,但在有些時候鲤妥,不相等,比如說做刪除矩陣里的元素操作時拱雏,我只改變了length的大小棉安,而size不變。

矩陣的創(chuàng)建

矩陣創(chuàng)建時首先要確定dshape铸抑,dshape有三種初始化方式:
例如要創(chuàng)建的矩陣的結(jié)構(gòu)為4行5列的二維矩陣贡耽,
方法一:

Dshape dshape;
dshape.shape[0] = 0;
dshape.shape[1] = 0;
dshape.shape[2] = 4;
dshape.shape[3] = 5;

方法二:

int a[]={0,0,4,5};
Dshape dshape;
initDshape(&dshape,a);

方法三:

Matrix *a; //a已是一個4行5列的二維矩陣
Dshape dshape;
dshape = a->dshape;

矩陣的創(chuàng)建構(gòu)造了以下函數(shù):
1.從數(shù)據(jù)創(chuàng)建數(shù)組

Matrix *creatAsMatrixFromDatas(double *data,int data_len, Dshape dshape);

淺拷貝,數(shù)據(jù)不開辟新的內(nèi)存空間蒲赂,array的地址就指向data的地址阱冶。

2.從數(shù)據(jù)創(chuàng)建數(shù)組,深拷貝,數(shù)據(jù)開辟新的內(nèi)存空間滥嘴,從data復(fù)制一份數(shù)據(jù)木蹬。

Matrix *creatMatrixFromDatas(double *data,int data_len, Dshape dshape);

使用示例:

Matrix *m = NULL;
m = creatMatrixFromDatas(data,data_len,dshape);

3.創(chuàng)建一個單一值的矩陣

Matrix *creatMatrixFromValue(double value, Dshape dshape);

4.指定初始值和步長,創(chuàng)建等間隔值的矩陣若皱,結(jié)束的值根據(jù)矩陣的大小變化

Matrix *creatMatrixFromArange(double startVal, double stepVal,Dshape dshape);

5.指定初始值和結(jié)束值镊叁,創(chuàng)建等間隔的矩陣,間隔根據(jù)矩陣的大小變化

Matrix *creatMatrixFromLinspace(double startVal, double endVal,Dshape dshape);

6.創(chuàng)建全0矩陣

Matrix *creatZerosMatrix(Dshape dshape);

7.創(chuàng)建全1矩陣

Matrix *creatOnesMatrix(Dshape dshape);

8.創(chuàng)建二維單位矩陣走触,要求dshape里行數(shù)與列數(shù)相等晦譬。

Matrix *creatIdentitySecondOrderMatrix(Dshape dshape);

矩陣的shape相關(guān)的函數(shù)

1.初始化dshape

void initDshape(Dshape *dshape,int *shapeval);

2.修改dshape

int reshape(Matrix *m,Dshape dshape);

3.獲取矩陣的維數(shù)

int getMatrixNdim(Matrix *m);

矩陣打印的函數(shù)

1.打印矩陣的shape

void printShape(Matrix *m);

2.打印矩陣

void printarray(Matrix *m);

矩陣的清空與銷毀函數(shù)

1.清空矩陣

void clearMatrix(Matrix *m);

2.銷毀矩陣

void destroyMatrix(Matrix *m);

獲取矩陣的元素

1.獲取矩陣的元素

int getMatrixElem(Matrix *m,int dimen0,int dimen1,int dimen2,int dimen3,double *elem);

dimen表示維數(shù),例如要獲取3X3的二維矩陣m中第(1,1)個元素(下標從0開始計算):

double elem;
getMatrixElem(m,0,0,1,1,&elem);

函數(shù)返回的int為狀態(tài)指示用的互广,一般都設(shè)定為返回0為操作成功敛腌,返回-1為操作失敗。

2.修改矩陣的元素

int modifyMatrixElem(Matrix *m,int dimen0,int dimen1,int dimen2,int dimen3,double elem);

3.獲取矩陣的連續(xù)幾行

Matrix *getSecondOrderMatrixRows(Matrix *m,int startRow,int endRow);

下標從0開始計算惫皱,返回一個新的矩陣像樊,用法示例:

Matrix *n = NULL;
n = getSecondOrderMatrixRows(m,0,1); //獲取矩陣m的第一行

4.獲取矩陣的連續(xù)幾列

Matrix *getSecondOrderMatrixColumes(Matrix *m,int startColume,int endColume);

5.獲取矩陣的子矩陣

Matrix *getSecondOrderSubMatrix(Matrix *m,int startRow,int startColume,int endRow,int endColume);

6.獲取矩陣刪除指定一行和一列之后的子矩陣

Matrix *getSecondOrderLeftSubMatrix(Matrix *m,int row,int colume);

矩陣的基本操作

1.復(fù)制矩陣

Matrix *copyMatrix(Matrix *m);

2.轉(zhuǎn)置矩陣

int transposeSecondOrderMatrix(Matrix *m);

3.求二維矩陣的跡

double getSecondOrderMatrixTrace(Matrix *m);

4.交換二維矩陣的兩行

int swapSecondOrderMatrixRow(Matrix *m, int row1,int row2);

5.交換二維矩陣的兩列

int swapSecondOrderMatrixColume(Matrix *m, int colume1,int colume2);

6.二維矩陣的指定一行加、減逸吵、乘凶硅、除一個系數(shù)k

int kAddSecondOrderMatrixRow(Matrix *m, int row,double k);
int kSubSecondOrderMatrixRow(Matrix *m, int row,double k);
int kMulSecondOrderMatrixRow(Matrix *m, int row,double k);
int kDivSecondOrderMatrixRow(Matrix *m, int row,double k);

7.二維矩陣的指定一列加、減扫皱、乘足绅、除一個系數(shù)k

int kAddSecondOrderMatrixColume(Matrix *m, int colume,double k);
int kSubSecondOrderMatrixColume(Matrix *m, int colume,double k);
int kMulSecondOrderMatrixColume(Matrix *m, int colume,double k);
int kDivSecondOrderMatrixColume(Matrix *m, int colume,double k);

8.二維矩陣的指定兩行元素一一對應(yīng)相加減乘除:row1 = row1 +-*/ row2

int addSecondOrderMatrixRows(Matrix *m, int row1,int row2);
int subSecondOrderMatrixRows(Matrix *m, int row1,int row2);
int mulSecondOrderMatrixRows(Matrix *m, int row1,int row2);
int divSecondOrderMatrixRows(Matrix *m, int row1,int row2);

9.二維矩陣的指定兩列元素一一對應(yīng)相加減乘除:colume1 = colume1 +-*/ colume2

int addSecondOrderMatrixColumes(Matrix *m, int colume1, int colume2);
int subSecondOrderMatrixColumes(Matrix *m, int colume1, int colume2);
int mulSecondOrderMatrixColumes(Matrix *m, int colume1, int colume2);
int divSecondOrderMatrixColumes(Matrix *m, int colume1, int colume2);

10.刪除二維矩陣的指定行數(shù)

int deleteSecondOrderMatrixRows(Matrix *m,int startRow,int endRow);

11.刪除二維矩陣的指定列數(shù)

int deleteSecondOrderMatrixColumes(Matrix *m,int startColume,int endColume);

12.刪除二維矩陣的指定一行和一列

int deleteSecondOrderMatrixRowAndColume(Matrix *m,int row,int colume);

13.按行拼接兩個矩陣,要求兩個矩陣一行的元素數(shù)目要相等

int spliceSecondOrderMatrixRow(Matrix *m1,Matrix *m2);

14.按列拼接兩個矩陣韩脑,要求兩個矩陣一列的元素數(shù)目要相等

int spliceSecondOrderMatrixColume(Matrix *m1,Matrix *m2);

15.二維矩陣整體加氢妈、減、乘段多、除一個系數(shù)k

int kAddMatrix(Matrix *m,double k);
int kSubMatrix(Matrix *m,double k);
int kMulMatrix(Matrix *m,double k);
int kDivMatrix(Matrix *m,double k);

16.兩個矩陣相加首量,得到一個新的矩陣,要求兩個矩陣的shape要一致

Matrix *addSecondOrderMatrixs(Matrix *m1,Matrix *m2);

17.兩個矩陣相減进苍,得到一個新的矩陣加缘,要求兩個矩陣的shape要一致

Matrix *subSecondOrderMatrixs(Matrix *m1,Matrix *m2);

18.兩個矩陣求點乘,得到一個新的矩陣觉啊,要求兩個矩陣的shape要一致

Matrix *dotSecondOrderMatrixs(Matrix *m1,Matrix *m2);

19.兩個矩陣求叉乘拣宏,m1為m X n矩陣,m2為n X p矩陣杠人,乘積返回一個m X p矩陣

Matrix *mulSecondOrderMatrixs(Matrix *m1,Matrix *m2);

矩陣的高級操作

1.求一個二維方陣的行列式

int detSquareMatrixs(Matrix *m,double *result);

2.求二維方陣中指定元素的代數(shù)余子式

int getSquareMatrixElemAlgebraicComplement(Matrix *m,int row,int colume,double *result);

3.求二維方陣中指定一行元素的代數(shù)余子式

Matrix *getSquareMatrixRawAlgebraicComplement(Matrix *m,int row);

4.求二維方陣的伴隨矩陣

Matrix *getSquareMatrixAdjointMatrix(Matrix *m);

5.求解二維方陣的逆矩陣

Matrix *invSquareMatrix(Matrix *m);

6.求二維矩陣的最簡階梯陣

Matrix *getEchelonMatrix(Matrix *m);

7.求二維矩陣的秩

int getSecondOrderMatrixRank(Matrix *m ,int *rank);

8.求齊次線性方程組AX=0的解,結(jié)果為全0矩陣或基礎(chǔ)解系構(gòu)成的矩陣

Matrix *solveHomoLinearEquations(Matrix *A);

9.求非齊次線性方程組AX=B的解勋乾,返回NULL表示無解宋下;一列矩陣表示唯一解;多列矩陣中辑莫,除了最后一列為特解学歧,前面幾列為基礎(chǔ)解系

Matrix *solveNonHomoLinearEquations(Matrix *A, Matrix *B);

10.求矩陣的無窮范數(shù)

double getMatrixInfNorm(Matrix *m);

11.求矩陣的L0范數(shù)

double getMatrixL0Norm(Matrix *m);

12.求矩陣的L1范數(shù)

double getMatrixL1Norm(Matrix *m);

13.求矩陣的L2范數(shù)

double getMatrixL2Norm(Matrix *m);

14.求矩陣的L21范數(shù)

double getMatrixL21Norm(Matrix *m);

To do list

1.求特征值與特征向量
2.奇異值分解(SVD)
3.QR分解
4.最小二乘解
5.矩陣的核范數(shù)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市各吨,隨后出現(xiàn)的幾起案子枝笨,更是在濱河造成了極大的恐慌,老刑警劉巖绅你,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件伺帘,死亡現(xiàn)場離奇詭異昭躺,居然都是意外死亡忌锯,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進店門领炫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來偶垮,“玉大人,你說我怎么就攤上這事帝洪∷贫妫” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵葱峡,是天一觀的道長砚哗。 經(jīng)常有香客問我,道長砰奕,這世上最難降的妖魔是什么蛛芥? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮军援,結(jié)果婚禮上仅淑,老公的妹妹穿的比我還像新娘。我一直安慰自己胸哥,他們只是感情好涯竟,可當我...
    茶點故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著空厌,像睡著了一般庐船。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嘲更,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天筐钟,我揣著相機與錄音,去河邊找鬼哮内。 笑死盗棵,一個胖子當著我的面吹牛壮韭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播纹因,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼喷屋,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了瞭恰?” 一聲冷哼從身側(cè)響起屯曹,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎惊畏,沒想到半個月后恶耽,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡颜启,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年偷俭,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片缰盏。...
    茶點故事閱讀 39,779評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡涌萤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出口猜,到底是詐尸還是另有隱情负溪,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布济炎,位于F島的核電站川抡,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏须尚。R本人自食惡果不足惜崖堤,卻給世界環(huán)境...
    茶點故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望恨闪。 院中可真熱鬧倘感,春花似錦、人聲如沸咙咽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽钧敞。三九已至蜡豹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間溉苛,已是汗流浹背镜廉。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留愚战,地道東北人娇唯。 一個月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓齐遵,卻偏偏與公主長得像,于是被迫代替她去往敵國和親塔插。 傳聞我的和親對象是個殘疾皇子梗摇,可洞房花燭夜當晚...
    茶點故事閱讀 44,700評論 2 354

推薦閱讀更多精彩內(nèi)容