說明:
稀疏矩陣的快速轉置算法的核心在於,用一個數組num記錄原來矩陣中的每列非零元個數,用另一個數組cpos來記錄原矩陣每列第一個非零元在新矩陣中的位置,以此來達到快速轉置的目的。
用這樣的方法,主要是希望,矩陣轉置後,存儲順序依然是按照行來存儲的。
1.實現及代碼註釋
根據上面的核心提示,可以有如下的代碼,下面的代碼中的註釋已經非常詳細,因此這裏就不把每一部分實現的功能獨立開來了:
#include<stdio.h> #include<stdlib.h> #define OVERFLOW -1 #define OK 1 #define ERROR 0 #define TRUE 2 #define FALSE -2 typedef int ElemType; typedef int Status; typedef struct{ //非零元三元組類型結構體 int i, j; //非零元的行和列 ElemType e; //非零元的值 } Triple; //非零元三元組類型結構體定義關鍵字 typedef struct{ //矩陣類型結構體 Triple *data; //data域,指向非零元三元組的結構體指針 int mu, nu, tu; //矩陣的行數、列數和非零元個數 } TSMatrix; //矩陣類型結構體定義關鍵字 /* 0 14 0 0 -5 0 -7 0 0 0 36 0 0 28 0 mu = 3; nu = 5; tu = 5 */ Status CreateSMatrix(TSMatrix &M){ //創建一個稀疏矩陣 M.tu = 5; M.data = (Triple*)malloc(sizeof(Triple) * (M.tu + 1)); //data域存儲元素的大小比稀疏矩陣的非零元個數大1,是因爲data[0]不使用 if(NULL == M.data) return OVERFLOW; M.data[1].i = 1; M.data[1].j = 2; M.data[1].e = 14; M.data[2].i = 1; M.data[2].j = 5; M.data[2].e = -5; M.data[3].i = 2; M.data[3].j = 2; M.data[3].e = -7; M.data[4].i = 3; M.data[4].j = 1; M.data[4].e = 36; M.data[5].i = 3; M.data[5].j = 4; M.data[5].e = 28; M.mu = 3; M.nu = 5; return OK; } Status FastTransposeSMatrix(TSMatrix M, TSMatrix &T){ //採用順序表存儲表示,求稀疏矩陣M的轉置矩陣T int j, p, q, t; /*j記錄遍歷時的當前列,cops[j],則表示當前列第一個非零元的位置或者該列非零元位置的其它位置(cops[j]++),正式轉置時用; p記錄遍歷時的非零元個數,正式轉置時用; q記錄cops[j],簡化代碼的表示,正式轉置時用 ; t用在轉置準備時。 */ int *num; //保存每一列的非零元個數 int *cpos; //保存轉置後每列第一個非零元在T中所處的序號 //cops[j]++則是該列的下一個非零元,如果存在的話 T.mu = M.nu; T.nu = M.mu; T.tu = M.tu; //初始化矩陣T T.data = (Triple*)malloc(sizeof(Triple)*(T.nu + 1)); num = (int*)malloc((M.nu + 1)*sizeof(int)); //num和cpos開闢空間比非零元個數大1,是因爲不使用0號位置 cpos = (int*)malloc((M.nu + 1)*sizeof(int)); if(num == NULL || cpos == NULL) return OVERFLOW; if(T.tu != 0){ for(j = 1; j <= M.nu; j++) //初始化num向量 num[j] = 0; for(t = 1;t <= M.tu; t++) //求M中每一列所含非零元的個數 num[M.data[t].j]++; //這裏要用到num[1]~num[5],所以上面num要全部初始化爲0 cpos[1] = 1; //這裏是一定的 for(j = 2;j <= M.nu; j++) //求每列的第一個非零元在T.data中的序號 cpos[j] = cpos[j-1] + num[j-1]; //畫表分析得出該公式並不難 for(p = 1; p <= M.tu; p++){ //上面是準備工作,下面開始正式轉置 j = M.data[p].j; //j的作用是記錄當前遍歷的列,以讓cops使用 q = cpos[j]; //是爲了簡化代碼,因爲下面都要用到cpos[j] T.data[q].i = M.data[p].j; //交換行 T.data[q].j = M.data[p].i; //交換列 T.data[q].e = M.data[p].e; //賦值 ,無論如何交換,儲存順序是已經定下來的了 cpos[j]++; //cops[j]++則是該列的下一個非零元,如果存在的話,不存在的話也沒有影響 } //因爲在這個for循環中,如果列變了,即j變化了,cpos[j]也不是原來的值了 } free(num); free(cpos); return OK; } int main(void){ int i,j; TSMatrix M; TSMatrix T; CreateSMatrix(M); FastTransposeSMatrix(M, T); printf("\n"); return 0; }
可以用C free等編譯器進行編譯運行,但由於時間關係,上面的代碼中並沒有給出轉置後的矩陣打印的代碼,可以自己加上去,當然也可以通過調試的方法監視新矩陣T中的data域的數值變化。
2.測試
測試就是按照上面的提示去做就可以了,時間關係,這裏就先不做測試,改天有時間再補上吧。