• 对角矩阵的压缩存储


    对角矩阵

    ●定义

    • 若一个n阶方阵A满足,其所有非零元素都集中在以对角线为中心的带状区域中,则称其为n阶对角矩阵

    ●术语

            • b - 矩阵半带宽:主对角线上下方各有b条次对角线
            • (2b+1)--矩阵的带宽

    ● 特征

            • 对于半带宽为 b(0<=b<(n-1))的对角矩阵,其|i-j|<=b的元素 ai,j不为零,其余元素为零.

    ●存储策略:

            •为了压缩存储空间,为0的空间,我们就不存储,或者判断出不是带状区域就输出 0
            •找到对角矩阵坐标和一维数组的关系,进而对坐标进行换算,映射一维数组位序
            •设计算法,保证逻辑结构不变,存储空间减小
            • 利用一维数组,按顺序存储对角矩阵的元素

    ●观察对角矩阵的结构(我们此处以三对角矩阵举例):

            •在三对角矩阵中,除了第一行和最后一行各有两个元素,其余各行非零元素aij均有三个,所以共有(3n-2)个非零元素 ,(第一行和最后一行,节点个数为2两个)
            • 处于对角线下方的节点,(a10,a21,a32,...),观察得出,有:j = i-1;
            • 处于对角线上的节点,(a00,a11,a22,...),有 : j=i;
            • 处于对角线上方的节点,(a01,a12,a23,...),有: j=i+1;

    ●寻找二维坐标和一位数组的位序关系

    •方法一: 输入坐标的时候,可以判断,然后确定是哪个位置上的节点,从而得出对应的一维数组的位序
            •方法二:① 观察
                    ② 先确定节点,前i行的元素个数,为: 2+3*(i-1)=3i-1;
                     因为,第一行和最后一行有两个元素,所以先把第一行算上,然后再算剩余i-1行,即可.
                    ③ 对角线下方的节点, aij是本行第一个非零元素,所以其前面的元素是k = 3i-1 = 2i+j
                    ④ 对角线的节点,是本行的第二个非零元素, k = 3i = 2i+j
                    ⑤ 对角线上方的节点,是本行的第三个非零元素, k = 3i+1 = 2i+j;
            •我们一维数组是从0开始计算的,所以元素前面的节点个数,就是对应的坐标位序


    ●下面我们开始构建三对角矩阵代码:

    1. #include
    2. #include
    3. #define N 6
    4. //构建一维数组数组
    5. void Init(int *&b)
    6. {
    7. b = (int*)malloc(sizeof(int)*(3*N-1));
    8. }
    9. //将e赋值给对应的二维数组A[i][j]里面的值,存储在一维数组里面
    10. void Assign(int b[],int e,int i, int j)
    11. {
    12. if(j == i-1)
    13. {
    14. b[3*i-1] = e;
    15. }
    16. else if(j == i)
    17. {
    18. b[3*i] = e;
    19. }
    20. else if(j==i+1)
    21. {
    22. b[3*i+1] = e;
    23. }
    24. }
    25. //返回特定坐标里面的数值
    26. int Value(int b[],int i, int j)
    27. {
    28. if(j == i-1)
    29. {
    30. return b[3*i-1];
    31. }
    32. else if(j == i)
    33. {
    34. return b[3*i];
    35. }
    36. else if(j==i+1)
    37. {
    38. return b[3*i+1];
    39. }
    40. else
    41. {
    42. return b[3*N-2];
    43. }
    44. }
    45. //逐个输出二维数组里面的数据
    46. void Disp(int b[])
    47. {
    48. int i,j;
    49. for(i=0; i
    50. {
    51. for(j = 0; j
    52. {
    53. printf("%4d",Value(b,i,j));
    54. }
    55. printf("\n");
    56. }
    57. }
    58. //销毁存储空间
    59. void Destroy(int b[])
    60. {
    61. free(b);
    62. }
    63. int main()
    64. {
    65. //构建一维数组
    66. //一维数组在元素矩阵个数的基础上加一,存放两侧的数据
    67. int *b1;
    68. //坐标
    69. int i,j;
    70. //承载输入数据
    71. int v;
    72. //构建一位数组
    73. Init(b1);
    74. printf("请输入要压缩的带状数据两侧的数据是多少?\n");
    75. scanf("%d",&v);
    76. b1[3*N-2] = v;
    77. printf("请一次输入矩阵内的数据");
    78. for(i=0;i
    79. {
    80. printf("请输入第%d行的%d个元素\n",i+1,N);
    81. for(j = 0;j < N;j++)
    82. {
    83. scanf("%d",&v);
    84. Assign(b1,v,i,j);
    85. }
    86. }
    87. Disp(b1);
    88. Destroy(b1);
    89. return 0;
    90. }

    运行结果如图:

     

     

  • 相关阅读:
    selenium之常用定位
    曲线艺术编程 coding curves 第十三章 超级椭圆与超级方程(Superellipses and Superformulas)
    暑假加餐|有钱人和你想的不一样(第四天)+多目标萤火虫优化算法(Matlab代码)
    Python期末复习题:字符串与产生随机数
    深入详解Mybatis的架构原理与6大核心流程
    java-php-python--茶店订购管理系统-计算机毕业设计
    Nginx反向代理联动Tomcat实现多实例部署、动静分离、负载均衡
    【无标题】
    Linux环境开发工具yum、makefile的使用 【Linux】
    解决 Axios 跨域问题,轻松实现接口调用
  • 原文地址:https://blog.csdn.net/qq_57484399/article/details/127725810