如何修改C语言代码实现含上下对角零三角数组的向量压缩与读取
特殊对称零三角矩阵的压缩存储适配修改
问题背景
原有代码的压缩逻辑是适配主对角线下方全零的上三角矩阵,对应规则是仅当矩阵位置满足j >=i(列序号大于等于行序号)时存储非零值,其余位置返回0。
现在需要适配的特殊矩阵结构为:主对角线两侧对称分布的嵌套三角区域为固定零值,非零区域为左右两个三角的并集,以n=6为例的矩阵结构如下:
6 0 0 0 0 2 3 1 0 0 4 3 2 9 2 1 5 6 7 8 6 2 4 6 8 7 0 0 2 1 9 0 0 0 0 9
由于原有索引映射、存储、读取逻辑没有匹配新的非零区域规则,会出现压缩错位、还原矩阵错误的问题。
核心适配思路
- 先明确所有非零位置的判定规则:对于任意行号
x(从0开始计数),先计算两个边界值:- 左边界
lb = min(x, n-1 -x):该行从第0列到lb列的区域为左侧非零区 - 右边界
hb = max(x, n-1 -x):该行从hb列到最后一列的区域为右侧非零区 - 落在
lb < j < hb区间内的位置为固定零值,不需要存入压缩向量
- 左边界
- 重新计算压缩向量的索引偏移:逐行累计前面所有行的非零元素总数作为基础偏移,再计算当前行内的元素偏移,得到二维位置对应的一维向量索引。
- 调整存储、读取逻辑:仅对非零区域的位置执行向量读写,零区域直接返回固定零值,跳过存储。
关键代码修改
1. 重写索引计算函数NewIndex
替换原有仅累计上三角元素的逻辑,改为逐行累计实际非零元素数,计算行内偏移:
int NewIndex(int x, int y) { int total_offset = 0; const int n_minus_1 = n - 1; // 累计前面所有行的非零元素数,作为偏移基数 for (int i = 0; i < x; i++) { int row_lb = (i < n_minus_1 - i) ? i : (n_minus_1 - i); int row_hb = (i > n_minus_1 - i) ? i : (n_minus_1 - i); int left_cnt = row_lb + 1; int right_cnt = n - row_hb; total_offset += left_cnt + right_cnt; } // 计算当前行内的元素偏移 int cur_lb = (x < n_minus_1 - x) ? x : (n_minus_1 - x); int cur_hb = (x > n_minus_1 - x) ? x : (n_minus_1 - x); int row_offset; if (y <= cur_lb) { row_offset = y; } else { row_offset = (cur_lb + 1) + (y - cur_hb); } return total_offset + row_offset; }
2. 调整压缩存储函数Put
替换原有y >=x的判断条件,按新的非零区域规则执行写入:
void Put(int vec [], int x, int y, int v) { const int n_minus_1 = n - 1; int cur_lb = (x < n_minus_1 - x) ? x : (n_minus_1 - x); int cur_hb = (x > n_minus_1 - x) ? x : (n_minus_1 - x); // 仅非零区域的值需要写入压缩向量 if (y <= cur_lb || y >= cur_hb) { vec[NewIndex(x, y)] = v; } }
3. 调整向量读取函数Get
匹配非零区域规则,零区域直接返回0:
int Get(int vec [], int x, int y) { const int n_minus_1 = n - 1; int cur_lb = (x < n_minus_1 - x) ? x : (n_minus_1 - x); int cur_hb = (x > n_minus_1 - x) ? x : (n_minus_1 - x); // 中间零区域直接返回固定0 if (y > cur_lb && y < cur_hb) { return 0; } return vec[NewIndex(x, y)]; }
4. 调整压缩向量的容量
原有向量容量是按上三角矩阵计算的,会出现数组越界,需要按实际非零元素总数分配空间:
// 辅助函数:计算压缩向量需要的总长度 int calc_vec_size() { int total = 0; const int n_minus_1 = n -1; for (int i=0; i<n; i++) { int row_lb = (i < n_minus_1 -i) ? i : (n_minus_1 -i); int row_hb = (i > n_minus_1 -i) ? i : (n_minus_1 -i); total += (row_lb +1) + (n - row_hb); } return total; } // 主函数中的vec定义替换为: int vec[calc_vec_size()];
修改后的运行效果
- 压缩过程自动跳过所有零区域,仅存储实际非零值,向量长度没有冗余
- 读取过程自动还原所有零位置,输出的矩阵和生成的原始特殊矩阵完全一致,不存在索引错位
内容的提问来源于stack exchange,提问作者user15199447
相关产品推荐
相关产品推荐

