• 数据结构 压缩矩阵笔记


    /*
    数组的压缩储存:
        在一些高阶矩阵中,非零元素非常少,此时如果使用二维数组将造成
        储存空间的浪费,这时可只储存部分元素,从而提高储存空间的利用
        率,通常的做法是为多个相同值的元素只分配一个储存单元,对值为
        零的元素不分配储存单元。我们把非零元素个数远小于二维数组总元
        素个数,或元素分布呈一定规律的(对称矩阵,三角矩阵,对角矩阵)
        特殊矩阵压缩储存。
        
        对称矩阵:
            矩阵元素的值与下标的关系: 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;
    }
  • 相关阅读:
    react深入学习(资料,案例)
    match.exec深入学习
    实用插件表格行列隐藏显示
    下拉选项插件的实现
    表格操作eventTable
    [CentOS7] 挂载iso镜像文件到/media目录下
    [CentOS7] 设置开机启动方式(图形界面或命令行)
    [CentOS7] 磁盘分区(gdisk, fdisk)
    [CentOS7] minimal安装后 出现 没有ifconfig 无法ping 无法yum could not retrieve mirrorlist http://mirrorlist.centos.org/
    [C++]C,C++中使用可变参数
  • 原文地址:https://www.cnblogs.com/lnlin/p/6852236.html
Copyright © 2020-2023  润新知