如何将一个数组压缩成一个向量并正确地从中读取
How to compress aт array into a vector and properly read from it
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdbool.h>
#include <malloc.h>
#define n 6
void insertarray(int arr[n][n])
{ for(int j = 0; j < n; j++){
if(j==0){
for (int i = 0; i < n; i++){
arr[i][j] = rand()%50;
}
}
if(j==1){
for (int i = 0; i < n; i++){
if(i==0){
arr[i][j] = 0;
}
else if(i==5){
arr[i][j] = 0;
}
else arr[i][j] = rand()%50;
}
}
if(j==2){
for (int i = 0; i < n; i++){
if(i==0 || i==1 || i==4 || i==5){
arr[i][j] = 0;
}
else arr[i][j] = rand()%50;
}
}
if(j==3){
for (int i = 0; i < n; i++){
if(i==0 || i==1 || i==4 || i==5){
arr[i][j] = 0;
}
else arr[i][j] = rand()%50;
}
}
if(j==4){
for (int i = 0; i < n; i++){
if(i==0){
arr[i][j] = 0;
}
else if(i==5){
arr[i][j] = 0;
}
else arr[i][j] = rand()%50;
}
}
if(j==5){
for (int i = 0; i < n; i++){
arr[i][j] = rand()%50;
}
}
}
}
int NewIndex(int x, int y) //пересчет индексов
{ int j=0;
for(int i=0; i<x; i++) j+= n-i;
return j+y-x;
}
void Put(int vec [], int x, int y, int v) // Запись в вектор (сжатие)
{ if (y >=x) vec[NewIndex(x, y)] = v;
}
int Get(int vec [], int x, int y) // Чтение из вектора
{ if (y >=x) return vec[NewIndex(x, y)];
else return 0;
}
void printarray(int a[n][n])
{ for(int i = 0; i < n; i++)
{ for (int j = 0; j < n; j++)
printf("%3i", a[i][j]);
printf("\n");
}
}
int main()
{ int vec[n*n/2+n/2];
int array[n][n];
insertarray(array);
printarray(array);
for(int i = 0; i < n; i++)
for (int j = 0; j <n ; j++)
Put(vec, i, j, array[i][j]); //сжатие массива
for(int i = 0; i < n*n/2+n/2; i++) //выдача результата сжатия
printf("%3i", vec[i]);
printf("\n\n");
for(int i = 0; i < n; i++)
{ for (int j = 0; j < n; j++) //чтение из сжатого представления
printf("%3i", Get(vec,i,j));
printf("\n");
}
return 0;
}
好吧,我有一个完全有效的代码,它首先创建一个包含主对角线下的空元素的数组,将其压缩成一个向量,然后从中读取。但现在我必须制作一个数组,其中包含在对角线交叉上方和下方的两个三角形中的空元素。
它必须看起来像这样
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
第一步成功了:我生成了这样的数组,但问题是它没有正常压缩它。它需要转换所有不在三角形中的元素,但它压缩就像它只在主对角线下有空元素一样。阅读的问题在于它像过去一样读取数组,但也读取交叉点上方的空元素三角形。你能帮我重做代码吗?我添加了 运行 我的程序的图片
为了实现这个模式,我们测试我们当前的 列 是在我们当前的 行 相对于任一边缘的范围内,向上到我们的中途点。然后我们将计算倒过来。
将矩阵与数组相互转换只是遍历矩阵边界、writing/reading to/from 数组并推进数组指针的问题。
要压缩矩阵,我们需要应用计算的逆作为过滤器,仅存储非零值。解压缩遵循与我们最初的 fill
操作相同的逻辑,但取而代之的是从数组中获取。
注意这里计算的大小:
int vec[n*n/2 + n/2];
不会为结果创建大小正确的数组(对于大小 6
,这会产生 21
,而您至少需要 24
)。请查看下面的函数 non_zero_count
,以准确计算该模式针对任何给定尺寸生成的非零值的数量。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void fill_matrix(int sz, int m[sz][sz]) {
for (int i = 0; i < sz; i++) {
for (int j = 0; j < sz; j++) {
if ((i <= sz / 2 && j > i && j < sz - 1 - i) ||
(i > sz / 2 && j > sz - i - 1 && j <= i - 1))
m[i][j] = 0;
else
m[i][j] = rand() % 99 + 1;
}
}
}
void pack_matrix(int *array, int sz, int m[sz][sz]) {
for (int i = 0; i < sz; i++)
for (int j = 0; j < sz; j++)
if (!(i <= sz / 2 && j > i && j < sz - 1 - i) &&
!(i > sz / 2 && j > sz - i - 1 && j <= i - 1))
*array++ = m[i][j];
}
void unpack_matrix(int *array, int sz, int m[sz][sz]) {
for (int i = 0; i < sz; i++) {
for (int j = 0; j < sz; j++) {
if ((i <= sz / 2 && j > i && j < sz - 1 - i) ||
(i > sz / 2 && j > sz - i - 1 && j <= i - 1))
m[i][j] = 0;
else
m[i][j] = *array++;
}
}
}
void print_matrix(int sz, int m[sz][sz]) {
for (int i = 0; i < sz; i++) {
printf("[ ");
for (int j = 0; j < sz; j++)
printf("%02d ", m[i][j]);
printf("]\n");
}
}
int non_zero_count(int n) {
int is_even = n % 2 == 0;
return (n * n) - ((is_even ? n : n - 1) / 2) * (n - (is_even ? 2 : 1));
}
#define MSZ 6
int main(void) {
int matrix[MSZ][MSZ];
int matrix2[MSZ][MSZ];
int array[non_zero_count(MSZ)];
srand(time(NULL));
fill_matrix(MSZ, matrix);
print_matrix(MSZ, matrix);
puts("----");
pack_matrix(array, MSZ, matrix);
unpack_matrix(array, MSZ, matrix2);
print_matrix(MSZ, matrix2);
}
输出:
[ 59 00 00 00 00 79 ]
[ 91 50 00 00 25 37 ]
[ 24 85 19 23 24 25 ]
[ 67 97 54 14 12 34 ]
[ 44 78 00 00 14 01 ]
[ 25 00 00 00 00 12 ]
----
[ 59 00 00 00 00 79 ]
[ 91 50 00 00 25 37 ]
[ 24 85 19 23 24 25 ]
[ 67 97 54 14 12 34 ]
[ 44 78 00 00 14 01 ]
[ 25 00 00 00 00 12 ]
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdbool.h>
#include <malloc.h>
#define n 6
void insertarray(int arr[n][n])
{ for(int j = 0; j < n; j++){
if(j==0){
for (int i = 0; i < n; i++){
arr[i][j] = rand()%50;
}
}
if(j==1){
for (int i = 0; i < n; i++){
if(i==0){
arr[i][j] = 0;
}
else if(i==5){
arr[i][j] = 0;
}
else arr[i][j] = rand()%50;
}
}
if(j==2){
for (int i = 0; i < n; i++){
if(i==0 || i==1 || i==4 || i==5){
arr[i][j] = 0;
}
else arr[i][j] = rand()%50;
}
}
if(j==3){
for (int i = 0; i < n; i++){
if(i==0 || i==1 || i==4 || i==5){
arr[i][j] = 0;
}
else arr[i][j] = rand()%50;
}
}
if(j==4){
for (int i = 0; i < n; i++){
if(i==0){
arr[i][j] = 0;
}
else if(i==5){
arr[i][j] = 0;
}
else arr[i][j] = rand()%50;
}
}
if(j==5){
for (int i = 0; i < n; i++){
arr[i][j] = rand()%50;
}
}
}
}
int NewIndex(int x, int y) //пересчет индексов
{ int j=0;
for(int i=0; i<x; i++) j+= n-i;
return j+y-x;
}
void Put(int vec [], int x, int y, int v) // Запись в вектор (сжатие)
{ if (y >=x) vec[NewIndex(x, y)] = v;
}
int Get(int vec [], int x, int y) // Чтение из вектора
{ if (y >=x) return vec[NewIndex(x, y)];
else return 0;
}
void printarray(int a[n][n])
{ for(int i = 0; i < n; i++)
{ for (int j = 0; j < n; j++)
printf("%3i", a[i][j]);
printf("\n");
}
}
int main()
{ int vec[n*n/2+n/2];
int array[n][n];
insertarray(array);
printarray(array);
for(int i = 0; i < n; i++)
for (int j = 0; j <n ; j++)
Put(vec, i, j, array[i][j]); //сжатие массива
for(int i = 0; i < n*n/2+n/2; i++) //выдача результата сжатия
printf("%3i", vec[i]);
printf("\n\n");
for(int i = 0; i < n; i++)
{ for (int j = 0; j < n; j++) //чтение из сжатого представления
printf("%3i", Get(vec,i,j));
printf("\n");
}
return 0;
}
好吧,我有一个完全有效的代码,它首先创建一个包含主对角线下的空元素的数组,将其压缩成一个向量,然后从中读取。但现在我必须制作一个数组,其中包含在对角线交叉上方和下方的两个三角形中的空元素。 它必须看起来像这样
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
第一步成功了:我生成了这样的数组,但问题是它没有正常压缩它。它需要转换所有不在三角形中的元素,但它压缩就像它只在主对角线下有空元素一样。阅读的问题在于它像过去一样读取数组,但也读取交叉点上方的空元素三角形。你能帮我重做代码吗?我添加了 运行 我的程序的图片
为了实现这个模式,我们测试我们当前的 列 是在我们当前的 行 相对于任一边缘的范围内,向上到我们的中途点。然后我们将计算倒过来。
将矩阵与数组相互转换只是遍历矩阵边界、writing/reading to/from 数组并推进数组指针的问题。
要压缩矩阵,我们需要应用计算的逆作为过滤器,仅存储非零值。解压缩遵循与我们最初的 fill
操作相同的逻辑,但取而代之的是从数组中获取。
注意这里计算的大小:
int vec[n*n/2 + n/2];
不会为结果创建大小正确的数组(对于大小 6
,这会产生 21
,而您至少需要 24
)。请查看下面的函数 non_zero_count
,以准确计算该模式针对任何给定尺寸生成的非零值的数量。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void fill_matrix(int sz, int m[sz][sz]) {
for (int i = 0; i < sz; i++) {
for (int j = 0; j < sz; j++) {
if ((i <= sz / 2 && j > i && j < sz - 1 - i) ||
(i > sz / 2 && j > sz - i - 1 && j <= i - 1))
m[i][j] = 0;
else
m[i][j] = rand() % 99 + 1;
}
}
}
void pack_matrix(int *array, int sz, int m[sz][sz]) {
for (int i = 0; i < sz; i++)
for (int j = 0; j < sz; j++)
if (!(i <= sz / 2 && j > i && j < sz - 1 - i) &&
!(i > sz / 2 && j > sz - i - 1 && j <= i - 1))
*array++ = m[i][j];
}
void unpack_matrix(int *array, int sz, int m[sz][sz]) {
for (int i = 0; i < sz; i++) {
for (int j = 0; j < sz; j++) {
if ((i <= sz / 2 && j > i && j < sz - 1 - i) ||
(i > sz / 2 && j > sz - i - 1 && j <= i - 1))
m[i][j] = 0;
else
m[i][j] = *array++;
}
}
}
void print_matrix(int sz, int m[sz][sz]) {
for (int i = 0; i < sz; i++) {
printf("[ ");
for (int j = 0; j < sz; j++)
printf("%02d ", m[i][j]);
printf("]\n");
}
}
int non_zero_count(int n) {
int is_even = n % 2 == 0;
return (n * n) - ((is_even ? n : n - 1) / 2) * (n - (is_even ? 2 : 1));
}
#define MSZ 6
int main(void) {
int matrix[MSZ][MSZ];
int matrix2[MSZ][MSZ];
int array[non_zero_count(MSZ)];
srand(time(NULL));
fill_matrix(MSZ, matrix);
print_matrix(MSZ, matrix);
puts("----");
pack_matrix(array, MSZ, matrix);
unpack_matrix(array, MSZ, matrix2);
print_matrix(MSZ, matrix2);
}
输出:
[ 59 00 00 00 00 79 ]
[ 91 50 00 00 25 37 ]
[ 24 85 19 23 24 25 ]
[ 67 97 54 14 12 34 ]
[ 44 78 00 00 14 01 ]
[ 25 00 00 00 00 12 ]
----
[ 59 00 00 00 00 79 ]
[ 91 50 00 00 25 37 ]
[ 24 85 19 23 24 25 ]
[ 67 97 54 14 12 34 ]
[ 44 78 00 00 14 01 ]
[ 25 00 00 00 00 12 ]