• 再议动态二维数组,通过一句表达式完成矩阵的转置


    先来回顾一下通常动态二维数组的创建过程,这里以 m×n int数组为例

    	int **pp=new int*[m];
    	for(int i=0;i<m;++i)
    		*(pp+i)=new int[n];
    
    	//通过*(*(pp+i)+j)操作数组元素(i,j)
    
    	for(i=0;i<m;++i)
    		delete [] *(pp+i);
    	delete [] pp;

    这样的方式称为离散动态数组,主要存在两个缺点:

    1. 数组储存区不连续;

    2. 堆上空间释放比较麻烦。

    图中以m=4,n=3为例。


    所以我们寻求更好的代码:

    	int *p=new int[m*n];
    	int **pp=new int*[m];
    	for(int i=0;i<m;++i)
    		*(pp+i)=p+i*n;
    
    	delete [] pp;
    	delete [] p;

    同样通过 *(*(pp+i)+j) 访问数组成员(i,j),先申请一段连续的空间,然后让指针数组保存它们的地址。

    图中,m=4,n=3,这样做有两个好处:

    1. 空间的释放更方便了;

    2. 可以重新操作这段空间组成新数组。相较于第一种方式,其额外的开销仅是一个int*变量。


    比如要把m×n个int所组成的空间段重分配为k×j的数组:

    	delete [] pp;
    	pp=new int*[k];
    	for(int i=0;i<k;++i)
    		*(pp+i)=p+i*j;

    图中,以k=2,j=6为例。


    通过观察代码,不难发现对于任意的i,都有

    		*(pp+i)=p+i*n;

    那么此时对于二维数组的操作事实上不需要二级指针的参与,只需一句表达式即可以用元素(i,j):

    	int *p=new int[m*n];
    
    	//*(p+i*n+j)——(i,j)
    
    	delete [] p;

    其实矩阵这个概念本来就是抽象的,把一个串拆分下并列着放就是矩阵了。对于这样的存储方式,可以很轻松的完成其转置,只要换一种引用方式:

                     *(p+i+j*n)

    即可完成矩阵的“转置”操作。事实上根本没有矩阵,存在的只是在内存中的一块连续空间而已,不同的访问方式显示了这块内存段在我们大脑中不同的映射。

    这里并不是按常规的思维方式,先形成一个二维数组,如A(m,n),然后填充,而是创建一个串,按某种规则写入数据,按某种规则读取数据。对于普通的矩阵操作,其读写规则为同一种。

    而对于一个矩阵转置问题,其本质是,按某种规则写入数据,按另一种规则读取数据,而这两种规则的不同点反映出矩阵转置的概念。内存段没变,变的是它在我们大脑中映射的矩阵,或者更准确的说是映射的规则变了。


  • 相关阅读:
    web service--基础概念(1)
    java web--国际化 i18n
    洛谷 P3842 [TJOI2007]线段
    洛谷 P6205 [USACO06JAN]Dollar Dayz S
    洛谷 P5414 [YNOI2019]排序
    洛谷 P1681 最大正方形II
    洛谷 P2327 [SCOI2005]扫雷
    洛谷 P1373 小a和uim之大逃离
    洛谷 P4317 花神的数论题
    洛谷 P4127 [AHOI2009]同类分布
  • 原文地址:https://www.cnblogs.com/silyvin/p/9106915.html
Copyright © 2020-2023  润新知