数组的基础知识

来源:互联网 发布:视频播放器 for mac 编辑:程序博客网 时间:2024/05/10 13:16
数组的定义:
        数组是由一组类型相同的数据元素构成的有序集合,每个数据元素称为一个数组元素(简称为元素),每个元素受n(n≥1)个线性关系的约束,每个元素在n个线性关系中的序号i1、i2、…、in称为该元素的下标,并称该数组为 n 维数组。 
数组的特点:
        元素本身可以具有某种结构,属于同一数据类型; 数组是一个具有固定格式和数量的数据集合。



二维数组的定义:

基本操作:
InitArray (&A, n, bound1, ..., boundn)
操作结果:若维数 n 和各维长度合法,则构造相应的数组A,并返回OK。 

DestroyArray(&A)
操作结果:销毁数组A。

Value(A, &e, index1, ..., indexn)
初始条件:A是n维数组,e为元素变量,随后是n 个下标值。   
操作结果:若各下标不超界,则e赋值为所指定的A的元素值,并返回OK。

Assign(&A, e, index1, ..., indexn)
初始条件:A是n维数组,e为元素变量,随后是n 个下标值。
操作结果:若下标不超界,则将e的值赋给所指定的A的元素,并返回OK。 

数组的基本操作:
⑴ 存取:给定一组下标,存储或读出对应的数组元素; 
⑵ 修改:给定一组下标,修改与其相对应的数组元素。 
存取和修改操作本质上只对应一种操作——寻址 

数组一般没有插入和删除操作,所以,一般不用预留空间,适合采用顺序存储。 

数组的顺序表示和实现
类型特点: 1) 只有引用型操作,没有加工型操作; 2) 数组是多维的结构,而存储空间是一个一维的结构。
有两种顺序映象的方式: 1)以行序为主序(低下标优先); 2)以列序为主序(高下标优先);

设一维数组的下标的范围为闭区间[l,h],每个数组元素占用 c 个存储单元,则其任一元素 ai 的存储地址可由下式确定:  Loc(ai)=Loc(al) + (i-l)×c 



数组的顺序表示和实现—二维
常用的映射方法有两种: 
        按行优先:先行后列,先存储行号较小的元素,行号相同者先存储列号较小的元素。  
        按列优先:先列后行,先存储列号较小的元素,列号相同者先存储行号较小的元素。

按列优先存储的寻址方法与此类似。




数组的顺序表示和实现—N维



练习:



矩阵的压缩存储 
1. 什么是压缩存储?
        若多个数据元素的值都相同,则只分配一个元素值的存储空间,且零元素不占存储空间。 
2. 什么样的矩阵具备压缩条件?       
        特殊矩阵(对称矩阵,对角矩阵,三角矩阵) 和稀疏矩阵。 

特殊矩阵和稀疏矩阵
特殊矩阵:矩阵中很多值相同的元素并且它们的分布有一定的规律。 
稀疏矩阵 : 矩阵中非零元素的个数较少(一般小于5%) 
压缩存储的基本思想是: 
⑴ 为多个值相同的元素只分配一个存储空间; 
⑵ 对零元素不分配存储空间。

特殊矩阵的压缩存储—对称矩阵

如何压缩存储?
只存储下三角部分的元素。





特殊矩阵的压缩存储—对角矩阵  
        对角矩阵:所有非零元素都集中在以主对角线为中心的带状区域中,除了主对角线和它的上下方若干条对角线的元素外,所有其他元素都为零。



问题: 
        如果只存储稀疏矩阵中的非零元素,那这些元素的位置信息该如何表示? 
        解决思路: 对每个非零元素增开若干存储单元,例如存放其所在的行号和列号,便可准确反映该元素所在位置。 
        实现方法: 将每个非零元素用一个三元组(i,j,aij)来表示,则每个稀疏矩阵可用一个三元组表来表示。
将稀疏矩阵中的每个非零元素表示为: (行号,列号,非零元素值)——三元组
三元组表:将稀疏矩阵的非零元素对应的三元组所构成的集合,按行优先的顺序排列成一个线性表。






稀疏矩阵的转置操作

(1)每个元素的行下标和列下标互换(即三元组中的i和j互换); 
(2)T的总行数mu和总列数nu与M的不同(互换);         
(3)重排三元组内元素顺序,使转置后的三元组也按行(或列)为主序有规律的排列。 
上述(1)(2)较好实现,那应该如何实现(3)呢

方法Ⅰ 压缩转置
基本思想:
        直接取,顺序存。即在A的三元组顺序表中依次找第1列、第2列、…直到最后一列的三元组,并将找到的每个三元组的行、列交换后顺序存储到B的三元组顺序表中。


算法Ⅰ 压缩转置——伪代码
1. 设置转置后矩阵B的行数、列数和非零元个数; 
2. 在B中设置初始存储位置pb; 
3. for (col=最小列号; col<=最大列号; col++)     
        3.1 在A中查找列号为col的三元组;     
        3.2 交换其行号和列号,存入B中pb位置;     
        3.3 pb++;




算法Ⅱ 快速转置
        基本思想:顺序取,直接存。即在A中依次取三元组,交换其行号和列号放到B 中适当位置。
如何确定当前从A中取出的三元组在B中的位置?
        分析:A中第1列的第一个非零元素一定存储在B中行下标为1的位置上,该列中其它非零元素应存放在B中后面连续的位置上,那么A中第2列的第一个非零元素在B中的位置便等于A中第1列的第一个非零元素在B中的位置加上A中第1列的非零元素的个数,以此类推。 

数据结构设计:
引入两个数组作为辅助数据结构: 
        num[nu]:存储矩阵A中某列的非零元素的个数; 
        cpot[nu]:初值表示矩阵A中某列的第一个非零元素在B中的位置。

设计思路:
        如果能预知M矩阵每一列(即T的每一行)的非零元素个数,又能预知第一个非零元素在b.data中的位置,则扫描a.data时便可以将每个元素准确定位(因为已知若干参考点)。
        请注意a.data特征:每列首个非零元素必定先被扫描到。
技巧:
        利用带辅助向量的三元组表,它正好携带每行(或列)的非零元素个数 NUM(i)以及每行(或列)的第一个非零元素在三元组表中的位置POS(i) 等信息。

快速转置——伪代码:
        1. 设置转置后矩阵B的行数、列数和非零元素的个数; 
        2. 计算A中每一列的非零元素个数; 
        3. 计算A中每一列的第一个非零元素在B中的下标; 
        4. 依次取A中的每一个非零元素对应的三元组;     
                4.1 确定该元素在B中的下标pb;     
                4.2 将该元素的行号列号交换后存入B中pb的位置;     
                4.3 预置该元素所在列的下一个元素的存放位置;

快速转置算法的效率分析:
        1. 与常规算法相比,附加了生成辅助向量表的工作。增开了2个长度为列长的数组(num[ ]和cpos[ ])。 
2. 从时间上,此算法用了4个并列的单循环,而且其中前3个单循环都是用来产生辅助向量表的。        
        for(col = 1; col <=M.nu; col++)  循环次数=nu;          
        for( i = 1; i <=M.tu; i ++)            循环次数=tu;         
        for(col = 2; col <=M.nu; col++)  循环次数=nu;        
        for( p =1; p <=M.tu ; p ++ )       循环次数=tu;  
该算法的时间复杂度=(nu*2)+(tu*2)=O (nu+tu) 
讨论:最恶劣情况是tu=nu*mu(即矩阵中全部是非零元素), 而此时的时间复杂度也只是O(mu*nu),并未超过传统转置算法的时间复杂度。




3 0
原创粉丝点击