/* 數組的壓縮儲存: 在一些高階矩陣中,非零元素非常少,此時如果使用二維數組將造成 儲存空間的浪費,這時可只儲存部分元素,從而提高儲存空間的利用 率,通常的做法是為多個相同值的元素只分配一個儲存單元,對值為 零的元素不分配儲存單元。我們把非零元素個數遠小於二維數組總元 素個數,或元素分布呈一定規律的(對稱矩陣,三角矩陣,對角矩陣) 特殊矩陣壓縮儲存。 對稱矩陣: 矩陣元素的值與下標的關系: a(i,j) = a(j,i) 我們只需為每一對稱元素分配一個儲存單元,這樣可以將 n*n 個 元素儲存在一個 n(n+1)/2 的儲存空間里。 假設用以為數組儲存上三角或下三角元素。則一維數組的下標 k 與 n 階對稱陣的元素 a(i,j) 的下標對應關系為: 如果 i >= j 時,以下三角儲存, k = i*(i+1)/2 + j 如果 i < j 時,以上三角儲存, k = j*(j+1)/2 + i 三角矩陣: 分為上三角矩陣和下三角矩陣,其中在上三角矩陣中,下三角元素 全部為一個常數c,下三角矩陣中,上三角元素全部為一個常數c。 以上三角矩陣為例,上三角矩陣的壓縮規則是只儲存上三角元素, 不儲存下三角元素,或只用一個儲存單元儲存下三角非零元素 用一維數組儲存上三角矩陣,采取使用一個儲存單元儲存下三角元 素的方法,一維數組的長度為 n*(n+1)/2 + 1 一維數組的下標 k與 n 階上三角矩陣的元素 a(i,j) 的下標對應關系為: 如果 i <= j, k = i*(2n-i+1)/2 + j -i 如果 i > j , k = n*(n+1)/2 下三角矩陣使用一維數組儲存后相應的對應關系為: 如果 i >= j, k = i*(i+1)/2 + j 如果 i < j, k = n*(n+1)/2 其中第 k = n*(n+1)/2 的位置存放的是常數 c 以上三角矩陣為例: # include <stdio.h> # define N 5 int main(void) { int arry[N][N]; int arr[N*(N+1)/2 + 1] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0}; int i, j, k; for (i = 0; i < N; ++i) { for (j = 0; j < N; ++j) { if (i <= j) { k = i*(2*N-i+1)/2 + j -i; arry[i][j] = arr[k]; } else { k = N*(N+1)/2; arry[i][j] = arr[k]; } } } for (i = 0; i < N; ++i) { for (j = 0; j < N; ++j) printf("%-5d", arry[i][j]); printf("\n"); } return 0; } 輸出結果: 1 2 3 4 5 0 6 7 8 9 0 0 10 11 12 0 0 0 13 14 0 0 0 0 15 對角矩陣:(數學上的問題 <-0-0->) 也稱為帶狀矩陣,就是所有的非零元素都集中在以對角線為中心的帶狀 區域內(對角線的個數位奇數),即除了主對角線和主對角線上下若干 條對角線的元素外,其它元素均為常數 c . */ /* 假設已有一個 n*n 的 上三角矩陣 A ,且上三角矩陣 A 的元素已按行為主序連續壓縮 存放在數組 B 中,設計一個算法,將 B 中的元素案列為主序連續壓縮存放在數組 C中 1 2 3 4 5 0 6 7 8 9 A(5*5) = 0 0 10 11 12 0 0 0 13 14 0 0 0 0 15 其中 B = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0}, C = { 1, 2, 6, 3, 7, 10, 4, 8, 11, 13, 5, 9, 12, 14, 15, 0}. 思路:將一維數組B還原成二維數組A,再將二維數組儲存在C中 */ # include <stdio.h> # define N 5 void Trans_To_Original(int arry[N][N], int * arr); void Trans_To_Compress(int arry[N][N], int * arr); void Show(int arry[N][N], int * arr1, int * arr2); int main(void) { // 創建一個一維數組儲存已知的以行為主序壓縮后所得元素 int B[(N+1)*N/2 + 1] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0}; int A[N][N] = {0}; Trans_To_Original(A, B); // 創建一個一維數組儲存以列為主序壓縮所得的數據 int C[(N+1)*N/2 + 1]; Trans_To_Compress(A, C); // 將三個數組打印輸出 Show(A, B, C); return 0; } void Trans_To_Original(int arry[N][N], int * arr) { int i, j, k; for (i = 0; i < N; ++i) { for (j = 0; j < N; ++j) { if (i <= j) { k = i*(2*N-i+1)/2 + j -i; arry[i][j] = arr[k]; } else { k = N*(N+1)/2; arry[i][j] = arr[k]; } } } return; } void Trans_To_Compress(int arry[N][N], int * arr) { int i, j, k = 0; // 按列為主序壓縮 for (i = 0; i < N; ++i) { for (j = 0; j <= i; ++j) { arr[k++] = arry[j][i]; } } arr[(N+1)*N/2] = 0; return; } void Show(int arry[N][N], int * arr1, int * arr2) { int i, j, k; printf("原二維數組為:\n"); for (i = 0; i < N; ++i) { printf(" "); for (j = 0; j < N; ++j) { printf("%-5d", arry[i][j]); } printf("\n"); } printf("以行為主序壓縮所得結果為:\n"); for (k = 0; k < (N+1)*N/2; ++k) { printf("%-3d", arr1[k]); } printf("\n以列為主序壓縮所得結果為:\n"); for (k = 0; k < (N+1)*N/2; ++k) { printf("%-3d", arr2[k]); } printf("\n"); return; }