/* 数组的压缩储存: 在一些高阶矩阵中,非零元素非常少,此时如果使用二维数组将造成 储存空间的浪费,这时可只储存部分元素,从而提高储存空间的利用 率,通常的做法是为多个相同值的元素只分配一个储存单元,对值为 零的元素不分配储存单元。我们把非零元素个数远小于二维数组总元 素个数,或元素分布呈一定规律的(对称矩阵,三角矩阵,对角矩阵) 特殊矩阵压缩储存。 对称矩阵: 矩阵元素的值与下标的关系: 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(" "); } 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("原二维数组为: "); for (i = 0; i < N; ++i) { printf(" "); for (j = 0; j < N; ++j) { printf("%-5d", arry[i][j]); } printf(" "); } printf("以行为主序压缩所得结果为: "); for (k = 0; k < (N+1)*N/2; ++k) { printf("%-3d", arr1[k]); } printf(" 以列为主序压缩所得结果为: "); for (k = 0; k < (N+1)*N/2; ++k) { printf("%-3d", arr2[k]); } printf(" "); return; }