稀疏数组实现

目录

一、介绍

二、具体操作

三、实现

四、全体代码


一、介绍

        当一个数组中大部分的元素为0或相同时,可以使用稀疏数组来保存这个数组。

二、具体操作

        1.记录数据几行几列,有多少个有效数据。

        2.将有效元素的行、列、值记录在一个数组中,达到压缩的效果。如下图:

原始数组                                                    稀疏数组

0 0 0 22 0 0 15                                              6      7      8        

0 11 0 0 0 17 0                                              0      3      22

0 0 0 -6 0 0 0                            =》               0      6      15

0 0 0 0 0 39 0                                                1      1      11

91 0 0 0 0 0 0                                                1      5      17      

0 0 28 0 0 0 0                                                2      3       -6

                                                                      3      5       39

                                                                      4      0        91

                                                                      5      2        28

        很简单就是将一维数组或二维数组压缩成一个二维数组,这个二维数组记录了原始数组有多少行、多少列,有多少个有效值。当然这是稀疏数组简单定义,在具体实现可以根据业务灵活变换。如你想让无效数组变成1为非0。

三、实现

1.压缩关键代码:

        首先遍历原始数组,得到有效数据的个数sum,然后根据sum定义出稀疏数组sparse,稀疏数组第一行记录和原始数组行数、列数、以及有效值个数。然后遍历原始数组,使用稀疏数组记录其有效值。

    int sum = 0;
    for (int i=0;i<7;i++)
    {
        for(int j=0;j<7;j++)
        {
            if (arr[i][j] != 0)
            {
                sum++;
            }
        }
    }

    int sparse[sum+1][3];

    sparse[0][0] = 7;
    sparse[0][1] = 7;
    sparse[0][2] = sum;

    int count=1;
    for (int i=0;i<7;i++)
    {
        for(int j=0;j<7;j++)
        {
            if (arr[i][j] != 0)
            {
                sparse[count][0]=i;
                sparse[count][1]=j;
                sparse[count++][2]=arr[i][j];
            }
        }
    }

2.解压关键代码:

        再稀疏数组的第一行拿到原始数组的行、列、以及有效值的个数,然后定义出原始数据,然后将原始数组全部元素先初始化为0,然后根据稀疏数组,还原原始数组相应位置的值。    

    int row,col,size;
    row = sparse[0][0];
    col = sparse[0][1];
    size = sparse[0][2];

    int arr[row][col];

    initArr(&arr[0][0],row,col);

    for (int i=1;i<row0;i++)
    {
        arr[arr[i][0]][arr[i][1]] = arr[i][2];
    }

3.将稀疏数组从内存写入到文件:

        首先我们写入将稀疏数组大小写入到文件开始位置,然后将稀疏数组其他数据按sizeof(int)大小一次写入文件。    

void writeToFile(int (*sparse)[3],int rows)
{
    FILE *fp = NULL;
    fp = fopen("./file","ab+");
    if (fp == NULL)
    {
        puts("open file failed");
        exit(-1);
    }
    int size = rows*3;
    //printf("size=%d\n",size);
    fwrite(&size,sizeof(int),1,fp);

    fwrite(&sparse[0],sizeof(int),size,fp);

    fclose(fp);
}

4.从文件中将稀疏数组读到内存:

        在读取文件时,我们先读int大小的数据,这就是size。然后根据size我们在堆上分配内存。最后将数据读到刚刚分配的内存中。数据读出来之后一切就好说了。

int* readFromFile(int *row)
{
    FILE *fp = NULL;
    fp = fopen("./file","rb+");
    if (fp == NULL)
    {
        puts("open file failed");
        exit(-1);
    }
    int size;
    fread(&size,sizeof(int),1,fp);
    //printf("size = %d\n",size);

    int *arr = (int*)malloc(size*sizeof(int));
    if (arr == NULL)
    {
        puts("malloc failed");
        exit(-1);
    }

    fread(arr,sizeof(int),size,fp);

    *row = size / 3;

    fclose(fp);

    return arr;
}

四、全体代码

        直接gcc main.c && ./a.out

#include<stdio.h>
#include <stdlib.h>
#include <string.h>

void printArr(int *arr,int row,int col);
void initArr(int *arr,int row,int col);
void writeToFile(int (*sparse)[3],int rows);
int* readFromFile(int *row);
void archiver();
void extract();

int arr[7][7]={
    {0,1,0,0,0,0,0},
    {0,2,0,0,0,0,0},
    {0,0,4,0,0,0,0},
    {0,0,0,5,0,0,0},
    {0,0,0,0,1,0,0},
    {0,0,0,0,0,0,19},
    {0,0,0,0,0,0,0},
};

void archiver(){
    puts("原始数组:");
    printArr(arr[0],7,7);

    int sum = 0;
    for (int i=0;i<7;i++)
    {
        for(int j=0;j<7;j++)
        {
            if (arr[i][j] != 0)
            {
                sum++;
            }
        }
    }

    int sparse[sum+1][3];

    sparse[0][0] = 7;
    sparse[0][1] = 7;
    sparse[0][2] = sum;

    int count=1;
    for (int i=0;i<7;i++)
    {
        for(int j=0;j<7;j++)
        {
            if (arr[i][j] != 0)
            {
                sparse[count][0]=i;
                sparse[count][1]=j;
                sparse[count++][2]=arr[i][j];
            }
        }
    }

    puts("稀疏数组如下:");
    printArr(sparse[0],sum+1,3);

    writeToFile(sparse,sum+1);
}


void extract(){
    int row0;
    int *p = readFromFile(&row0);
    int sparse[row0][3];

    puts("在文件中读到的稀疏数组:");
    printArr(p,row0,3);

    memcpy(&sparse[0],p,sizeof(int)*row0*3);

    free(p);

    int row,col,size;
    row = sparse[0][0];
    col = sparse[0][1];
    size = sparse[0][2];

    int arr[row][col];

    initArr(&arr[0][0],row,col);

    for (int i=1;i<row0;i++)
    {
        arr[sparse[i][0]][sparse[i][1]] = sparse[i][2];
    }
    puts("还原的数组如下:");
    printArr(arr[0],row,col);
}


int main(){
    archiver();
    extract();
 
    return 0;
}


void printArr(int *arr,int row,int col)
{   
    for (int i=0;i<row;i++)
    {
        for(int j=0;j<col;j++)
        {
            printf("%d ",*(arr + i*col +j));
        }
        printf("\n");
    }
}

void initArr(int *arr,int row,int col)
{   
    for (int i=0;i<row;i++)
    {
        for(int j=0;j<col;j++)
        {
            *(arr + i*col +j) = 0;
        }
    }
}


void writeToFile(int (*sparse)[3],int rows)
{
    FILE *fp = NULL;
    fp = fopen("./file","ab+");
    if (fp == NULL)
    {
        puts("open file failed");
        exit(-1);
    }
    int size = rows*3;
    //printf("size=%d\n",size);
    fwrite(&size,sizeof(int),1,fp);

    fwrite(&sparse[0],sizeof(int),size,fp);

    fclose(fp);
}

int* readFromFile(int *row)
{
    FILE *fp = NULL;
    fp = fopen("./file","rb+");
    if (fp == NULL)
    {
        puts("open file failed");
        exit(-1);
    }
    int size;
    fread(&size,sizeof(int),1,fp);
    //printf("size = %d\n",size);

    int *arr = (int*)malloc(size*sizeof(int));
    if (arr == NULL)
    {
        puts("malloc failed");
        exit(-1);
    }

    fread(arr,sizeof(int),size,fp);

    *row = size / 3;

    fclose(fp);

    return arr;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值