稀疏数组-矩阵存储【C语言实现】

稀疏数组

/*
 * @Author: itThree
 * @Date: 2021-09-10 15:48:10
 * @LastEditTime: 2021-09-15 15:58:50
 * @Description: 
 * @FilePath: \cpp\datas\sparseArr.cpp
 * 光阴之逆旅,百代之过客,而已
 */

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

void printArr(int *arr, int row, int col);

/**
 * 稀疏数组:将二维数组进行“压缩”;
 * 使用n+1行3列,其中n为原数组中有效(非零)元素个数,稀疏数组第0行用于存放行、列、元素总数信息故需n+1行
*/

//统计数组中元素的个数,用于确定稀疏数组的行数
int countElement(int* &p, int row, int col){
    int sum;
    int n = row*col;
    for(int i=0; i<n; i++){
        if(*(p+i) != 0){
            sum++;
        }
    }
    printf("sum:\t%d\n",sum);
    return sum;

}

//以指针形式接收矩阵(二维数组)
void createSparseArr2(int* arr, int row, int col ,int n){
    int sparse[n+1][3];
    sparse[0][0] = row;
    sparse[0][1] = col;
    sparse[0][2] = n;
    int sparseRow = 0;
    for(int i=0;i<row;i++){
        for(int j=0;j<col;j++){
            if(*(arr+i*col+j)!=0){
               sparseRow++;
               sparse[sparseRow][0] = i;
               sparse[sparseRow][1] = j;
               sparse[sparseRow][2] = *(arr+i*col+j);
           }
        }            
    }
    printArr((int*)sparse,n+1,3);
}
//这个稀疏数组的存储算法为n^2,还可用指针实现一个n。


//打印二维数组
void printArr(int *arr, int row, int col)
{//指针指向二维数组首地址,依靠row,col判别边界条件
    //遍历行
    for(int i=0;i<row;i++){
        //遍历列
        for(int j=0;j<col;j++)printf("%d \t",*(arr+i*col+j));
        printf("\n");
    }

}

int main(){
    int source[4][8]{
        {1,7,6,5,2,8,2,8},
        {2,7,6,5,2,8,2,8},
        {3,7,6,5,2,8,2,8},
        {4,7,6,5,2,8,2,8}
    };
    int* p;
    p = source[0];
    int n = countElement(p,4,8);
    printf("-------------------------------------------\n");
    
    createSparseArr2((int*)source,4,8,n);
    //int* i[4];
    //指针i指向二维数组的一行
    //i[0] = source[0];
    //i[1] = source [1];
    //i[2] = source [2];
    //i[3] = source [3];
    // createSparseArr1(i,4,8,n);
    return 0;
}

使用指针数组方式创建稀疏数组

//使用指针数组传值
void createSparseArr1(int* p1[], int row, int col, int n){
    //需要多一行来存储原数组大小信息
    int sparse[n+1][3];
    sparse[0][0] = row;
    sparse[0][1] = col;
    sparse[0][2] = n;
    //控制稀疏数组的行号
    int sparseRow = 0;
    for (int i = 0; i < row; i++)
   {
       for (int j = 0; j < col; j++)
       {    //原数数组索引处有无元素为判断条件,有则放入稀疏数组,无则进行下一次循环
           if(p1[i][j]!=0){
               //第0行已存放数据,故先行++
               sparseRow++;
               sparse[sparseRow][0] = i;
               sparse[sparseRow][1] = j;
               sparse[sparseRow][2] = p1[i][j];
           }
       }
       
   }
    printArr((int*)sparse,n+1,3);
}

遇到的问题:

强制转换数组首地址为指针返回不可行

image-20210915152000718

报错的地方:

int sparse[n+1][3];
return (int*) sparse;

解答:在函数执行完毕并return后sparse数组将被销毁,故无法将其强制转换为指针类型并返回;

不过,指定一个指针指向sparse并返回倒不成问题。

指针与数组地址

int source[4][8]{
        {1,7,6,5,2,8,2,8},
        {2,7,6,5,2,8,2,8},
        {3,7,6,5,2,8,2,8},
        {4,7,6,5,2,8,2,8}
    };
    int* p;
    p = source[0];
    int* i[4];
    //指针i指向二维数组的一行
    i[0] = source[0];
    i[1] = source [1];
    i[2] = source [2];
    i[3] = source [3];
//得出结果
	// source[0],source[0][0]在同一地址下
 	printf("p:\t%d\n", p);
    printf("source[0]:\t%d\n", source[0]);
    printf("&source[0][0]:\t%d\n", &source[0][0]);
    printf("source[0][0]:\t%d\n", source[0][0]);
    printf("*p:\t%d\n", *p);
	//使用指针数组指向二维数组每行首地址可行
    printf("i[1][i]:\t%d\n", i[1][2]);
	
    printf("*(p+31)\t%d\n", *(p+31));
	//下标溢出了哦!
    printf("*(p+32)\t%d\n", *(p+32));

运行结果:image-20210915153230219

posted @ 2021-09-15 21:00  main(void)  阅读(152)  评论(0编辑  收藏  举报
.c_ad_block { display: none !important; } #ad_t2{ display: none !important; }