数组技术

2024-06-26

数组技术(共7篇)

数组技术 篇1

0 引言

随着全三维数字设计产品数据管理技术的日渐成熟,三维机加工艺设计模型在实际生产应用中将逐步取代传统二维机加工艺图纸,实现对现场进行生产作业指导。基于数字化的三维机加工艺模型数据载体通常以轻量化演示文件格式进行存储并在专业演示软件中进行浏览,而演示文件的大小往往影响到三维机加工艺模型演示文件的数据管理难度与网络传输的效率,对工艺模型演示文件进行数据压缩成为其在应用中迫切需要解决的问题。在三维机加工艺模型中,大部分存储空间由几何模型数据占用,因此对三维机加工艺的几何模型的数据压缩显得尤为关键。针对三维CAD几何模型的压缩问题,国内外学者已进行了许多相关研究,例如文献[1]即通过对几何模型网格与顶点进行的简化。这些方法都是针对常规CAD模型提出的优化方案,而考虑到三维机加工艺的工序间模型存在大量重复三角面片的特点,通过对这些面片进行合理的重用往往可以有效地压缩三维机加工艺几何模型文件的大小。因此,本文将提出一种基于后缀数组的三维机加工艺几何模型的压缩方案,解决机加工艺演示文件的压缩问题。

1 几何模型STL文件格式与压缩方案

STL文件是当前CAD系统下较常用一种通用格式文件,其主要有文本文件(ASCII)和二进制文件2种格式[2]。实际应用时,由于ASCII文件格式占用空间较大,不适合模型轻量化文件的编码。本文主要介绍STL的二进制文件的组成方式,在STL二进制文件中保存的是模型的一个个三角面片的信息。文件的具体格式中起始部分存储着零件名称占80字节,接着是一个表示三角面片个数的4字节整数N,之后会有N组三角面片信息,每组三角面片信息由3个顶点数据,1个法向量数据,和三角面片属性数据组成,这些数据一共占用50个字节[3]。

对STL文件的轻量化压缩,已有许多经典解决方法,以下为2种较为常见的解决方案。

第1种压缩方式,是通过将STL文件里三角面片数据中的法矢量数据去除,进而为每个三角面片数据节省12字节的空间,虽然去除面片的法矢量可能会导致复杂表面的图形渲染效果下降,但是鉴于机械制造的零部件通常表面较规整,因此其对展示效果的影响是可以接受的。当数据加载后,需要对三角面片的法矢量进行补全,补全法矢量的方式是采用三角面片的是3个顶点直接计算该面片的外法矢量。外法矢量计算公式如下:

其中,为三维空间的法矢量,v1、v2、v3为三角面片的3个顶点坐标,且按逆时针分布。

第2种压缩途径是采用低空间占用的顶点索引来标记顶点的重复顶点,以节约文件存储空间[4],该方法常应用于GPU图形渲染等场景中。其方法是先将所有顶点去重排序后,保存为一个顶点序列,这样每个三维顶点就有唯一的4字节序列号,三角面片不再记录3个顶点的具体信息,直接记录3个4字节的索引序号,需要处理具体顶点时,再用顶点的索引序号在顶点序列中取出使用。由于三维零部件模型都是由封闭的几何面片构成,每个图形表面的网格顶点会被不少于3个不同的三角面片网格共用。以平均3个共享平面的下限计算,原本需要使用9个4字节的数据来记录着3个相同的顶点,而现在只需要3个4字节的数据记录顶点信息,同时用3个4字节的索引记录模型顶点的标号。因此该方案至少能实现顶点数据66.7%的压缩率,实际使用中,这个途径往往能达到40%以下的压缩率,可见该方案能有效地节约存储空间。

2 后缀数组

后缀数组是一种为文本索引设计的数据结构,该结构由记录了字符串的各个后缀的字典序索引的数组构成[5]。利用后缀数组的字典序特性可以快速实现字符串内相同连续子串的查找匹配问题。首先引入后缀数组相关定义。

定义1:1个n长字符串S的i后缀Suffix(S,i)指字符串S以第i个元素为起始字符的后缀,即Suffix(S,i)=SiSi+1Si+2…Sn[6]936。

定义2:1个n长字符串S的后缀数组SA指S所有后缀字典序排序后其索引构成的数组,即SA是1个由1~n排列构成的数组,且i<j时,满足Suffix(S,SA(i))<Suffix(S,SA(j))[6]936。

定义3:排序数组rank(i)指后缀Suffix(S,i)在后缀数组中的排序位置,即有SA(rank(i))=i。

定义4:对字符串S1与S2,定义lcp(S1,S2)指字符串S1与S2的最长公共前缀的长度[6]936。

定义5:对字符串S,定义height(i)表示SA(S)的i与i+1索引指代后缀的最长公共前缀长度,即height(i)=lcp(Suffix(S,SA(i)),Suffix(S,SA(i+1)))[6]936。

如表1所示为字符串S=aazbcbbcbcaa的后缀数组。

后缀数据的构造求解算法有许多,包括倍增算法、诱导拷贝算法与分治和递归算法[7]。本文主要介绍后缀数组的倍增算法的主体思想。

后缀数组的倍增算法过程:首先以每个后缀的第一关键字按计数排序的方式排序;之后假设当前索引数组已经完成n个字符串后缀按L长前缀为关键字的排序过程,再构造2L长前缀为关键字排序的索引数组,由于所有后缀串的L长前缀的排序已经完成,因此对于任意后缀Suffix(S,i)将其L长前缀排序位置作为第一关键字,而将后缀Suffix(S,i+L)的L长前缀的排序位置作为Suffix(S,i)的第二关键字,进行基数排序,通过这次基数排序索引数组可以完成n个后缀串的2L长前缀为关键字的排序,通过反复这个倍增过程最终获得所有后缀串的排序。因为,基数排序过程可以在O(n)的时间复杂度内完成,加之倍增过程恰有[log2n]次,所以整个过程的时间复杂度为O(nlog n)。

文献[8]介绍一种线性时间复杂度求解height数组的算法。改算法基于一个关于height数组的性质,当height(rank(i))=h时,height(rank(i+1))≥h-1。该算法流程如图1所示,该算法时间复杂度为O(n)。

3 机加工艺工序间模型压缩

3.1 机加工艺工序间模型文件原始编码

机加工艺通常由多个工序过程构成,每个工序会对上一步工序产生的零件物理模型做进一步的再加工而产生新的零件物理模型,通常将这些在整个机加工艺过程间各个过渡零件物理模型称为机加工艺的工序间模型。因此,一个三维机加工艺模型所包含的所有物理几何模型集合是从毛坯模型到加工零件成品模型的一系列工序间模型构成的。

参考传统STL格式文件的编码方式,本文对机加工艺工序间模型数据轻量化文件采用如下编码格式如图2所示。文件中起始部分是文件头,其中记录模型名称与工序间模型数量N这2个信息;紧接着是顶点数据段,存放所有工序间模型所涉及的顶点信息,其起始由4个字节的整型数据储存所有工序间模型包含的不同顶点数量,若一共有K个不同的顶点,那么接下来文件中依次存放K个浮点数三元集表示各个顶点的空间位置;再紧接着是工序间模型三角面片数据段,由N段数据块组成,每段数据块即一个工序间模型的三角面片数据,其中每段数据的起始4个字节是一个整型数据表示接下来有多少组三角面片数据组,每个三角面片数据组由3个整型顶点索引构成,每个整型索引代表顶点信息段中的对应顶点,3个顶点构成一个三角面片。

由于机加工艺中,其每一步工序只会在上一步工序产生的工序间模型基础上改变部分几何表面特征,而几何模型的大部分表面信息并没有发生变化,这使得相邻的工序间模型间存在大量相同的三角面片段,因此上述轻量化文件中的工序间模型三角面片数据段存在大量重复的数据片段。如果对这些重复的三角面片段数据信息进行合并,可以实现对机加工艺模型轻量化文件的进一步压缩。

3.2 重复数据段匹配

实现工序间模型的重复三角面片数据段压缩,首先要解决的是如何快速查找并匹配出相邻工序间模型的重复三角面片段。由于在轻量化文件中工序间模型的三角面片数据信息是由一串串索引序列组成,因此,相邻工序间模型的重复三角面片段匹配问题可以转换为2个字符串之间查找匹配重复连续子串的问题。

3.2.1 朴素匹配方法

该问题最简单的朴素求解方法是采用逐一匹配的方式完成。其具体过程是通过枚举2个待匹配字符串的起始位置,用指针依次匹配以该起始位置开始的后续字符串位置,直到不能匹配为止。对于长度为L1和L2的2个字符串,一共有L1·L2个起始匹配位置,每个起始位置最坏匹配min(L1,L2)个字符,因此该暴力算法的时间复杂度为O(L1·L2·min(L1,L2))。虽然对字符串长度在几百范围内的情况,这个算法在现代计算机上完全可以在很短的时间内解决,但是考虑到本文中编码构成的字符串是由几何模型三角面片的节点生成的,且工艺模型的三角面片常常出现数千至上万的级别,而在103~104的数量级上,该暴力算法会出现十分严重退化,往往运算时间会上升至几分钟甚至更多。

为了有效优化匹配效率,下文将利用后缀数组的方式来降低匹配过程的时间复杂度,从而实现高效的重复三角面片数据段匹配。

3.2.2 基于后缀数组算法的重复数据片段快速匹配

利用后缀数组进行工序间模型的重复三角面片数据段的快速匹配。首先将工序间模型的顶点索引序列视为字符串,每次匹配发生于相邻2个工序间模型之间,即如果总共有k+1个工序间模型,则需进行k次重复面片模型匹配。同时,在匹配过程中为了能使用基数排序算法,将所有顶点索引序号重映射至[0,N)的连续区间上。

匹配前先将待匹配的2个顶点序列串前后相连,并在相连接处加入不在区间[0,N)内的特殊序号$进行分割,即如带匹配的工序间模型顶点序列为sa与sb,则进行后缀数组运算的序列为s=sa+$+sb。其中,之所以加入特殊符号$是由于s的连续子串中包含由sa后缀串与sb前缀串组成的序列串,而这个序列串在sa与sb中都不存在,但这种本不存在的字符串会影响2个字符串间height数组的结果;因此加入特殊序号符$以保证height数组匹配出的最长公共前缀不会出现跨越sa与sb的情况。然后利用上述后缀数组的相关算法计算获得顶点序列s的SA数组、rank数组以及height数组。

根据所计算出的后缀数组相关信息,利用贪心算法,寻找顶点序列sb中在序列sa中出现的重复子序列。设sa与sb序列的长度分别为la与lb,其具体算法流程如下:

根据上述方法进行复杂度分析,后缀数组相关计算在O(Nlog N)的时间复杂度内完成,而上述过程最坏情况下也可O(N2)的时间复杂度内完成,因此2个相邻工序间模型的重复顶点子序列匹配可在O(N2)复杂度内完成。

实际上,上述贪心的匹配过程还存在优化的空间,其中STEP 06与STEP 08对应的过程可以在贪心算法开始前对SA数组进行扫描并预处理出每个下标对应的最近满足SA(i)<la的位置,这样贪心过程的STEP 06与STEP08可以降为O(1)的时间复杂度,同时在STEP 07与STEP 09处采用线段树等高级数据结构,可以将STEP 07与STEP 09的单次计算时间复杂度降为O(log N)甚至更低。因此,进行适当优化,该贪心算法时间复杂度可降为O(Nlog N)。但是出于本课题的应用场景字符串长度只在一般不超过104的数量级上,O(N2)复杂度已经十分有效。

3.3 重复数据段压缩编码与解压

新的数据编码方式在文件头与定点信息段部分采用3.1节所述原始编码方式进行数据编码。对于工序间模型三角面片数据段进行如下压缩编码,首先第一组工序间模型数据段与原始编码方式一致,其内容不变;当第k组工序间模型编码完成后,对第k+1组工序间模型进行压缩编码,其初始4个字节的整型数据依旧是该工序间模型所包含三角面片数量,接下来的三角面片数据段依次检测每一个索引字符,如果该索引字符在匹配中没有出现则正常写入文件,否则检测匹配段在第k组工序间模型中对应的匹配区间时,就不再写入该区间数据,而是直接用该区间的起始终止索引代替这段数据,例如第k+1个工序间模型三角面片段中[L1,R1]区间与第k个工序间模型三角面片段中[L0,R0]区间相同,那么在构造压缩文件时第k+1组工序间模型的三角面片数据在写到[L1,R1]区间时直接以2个4字节整型数据{-L0,-R0}代替,之所以采用负数,是为了区分该数据是索引还是区间序号。通过这个方法扫描一遍原始轻量化文件数据,即可获得压缩后的数据文件。

利用该方式压缩的工序间模型三角面片数据解压缩过程非常简单,通过依次扫描各个工序间模型的三角面片数据段,将压缩后的三角面片数据中的代表区间序号的数据用上一个工序间模型三角面片段对应区间中的数据填充,即可完成解压过程。

4 实验论证

为了验证所述工序间模型三角面片段重用方案的有效性,本文挑选了5个轻量化机加模型案例,分别采用经典压缩方法与三角面片段重用方法进行实验测试。表2为实验结果。

从表中不难看出,本文方法能有效地对原模型文件进行压缩,平均能将原始模型压缩至16%左右,尤其是针对模型文件较大较复杂的情况下,其优化效果更加明显。进一步分析发现这些模型工序较多,重复三角面片段出现的概率更大,因此优化效果更佳。

通过实验结果可以判断,本文所述三角面片重用方法是有效的。

参考文献

[1]Schroeder William J.,Zarge Jonathan A.,Lorensen William E.Decimation of Triangle Meshes[J].ACM SIGGRAPH Computer Graphics.1997,26(2):65-70.

[2]张贞贞,陈定方.基于VC的STL文件读取[J].湖北工业大学学报,2008,23(2):44-46.

[3]严梽铭,钟艳如.基于VC++和Open GL的STL文件读取显示[J].计算机系统应用,2009(03):172-175.

[4]朱林,常名.计算机图形学[M].Lin Zhu,Ming Chang,译.武汉:华中科技大学出版社,2001.

[5]张长利,赫枫龄,左万利.一种基于后缀数组的无词典分词方法[J].吉林大学学报(理学版),2004(04):548-553.

[6]Manber Udi,Myers Gene.Suffix arrays:A new method for on-line string searches.SIAM Journal on Computing.1993,22(5):935-948.

[7]张喜娟.基于后缀数组的近似字符串匹配[D].西安:西安电子科技大学,2012.

[8]Cormen T.H.算法导论[M].北京:机械工业出版社,2006.

数组排序算法浅析 篇2

顺序排序的主要思想是每一轮比较结束后都可以确定某一元素;在一轮的比较过程中, 将要确定的位置上的元素与其后所有的元素进行比较;对于一个长为N的数组, 需进行N-1轮比较。其第一轮的比较过程如下:

该轮中, a[0]与a[1]~a[n-1]的所有元素进行比较, 比较过程中, 如果发现哪个元素比a[0]小, 则与a[0]进行交换。一轮比较之后, 确定a[0]为数组中最小的元素。相同方法, 依次确定a[1]、a[2]、a[3]…a[n-2]。

由上表, 可以写出其实现代码

可以发现当数组原有的顺序是降序, 要实现其升序排序时, 每一轮中的交换的次数将会非常多, 严重影响排序效率。所以对该方法进行改进:先找出数组中最小值, 再与相应位置上的元素进行交换, 这就是选择排序。

选择排序的主要思想是每次从待排序的数据元素中选出最小的一个元素, 放在待排序数列的起始位置, 直到全部待排序列的数据元素全部排列完毕。

第一轮的比较过程如下:

选择排序的实现代码

选择排序相较于顺序排序有更高的执行效率, 而且思想同样利于理解。

冒泡排序的主要思想是“相邻元素”之间的比较, 如果前面的元素大于后面元素就把他们互换。一轮比较之后可以确定最后一个元素为最大, 第二轮比较之后可以确定最后一个元素为第二大的元素……依次类推, 第N-1轮比较, 可以确定倒数第二个元素, 这个时候数组的排序完成。冒泡排序的过程如下:

冒泡排序的实现代码

顺序排序算法, 思想简单易于理解且适于任何的数组, 无论什么情况下都可以使用;但是顺序排序效率较低, 可以采用选择排序法进行改进;即使如此选择排序的效率依然受到比较次数的影响, 所以对于比较元素比较少的数组, 可以采用冒泡排序法。

如果数组中99%的数值已经排序好, 即只有很少的元素需要进行排序, 可以选择冒泡排序法;如果你所要排序的数据数目相对较少并满足100个以下, 你就可以采用选择排序法;如果上述几种情况都不满足, 那么就选普遍适用的排序算法即顺序排序法即可。

以上所述只是三种常见排序, 在众多的排序算法中各有优缺点, 每一种算法只有在某一种情况下才表现的最好, 我们应当合理的根据实际情况选择算法。

参考文献

[1]张巍.基于Page Rank算法的搜索引擎优化策略研究[D].四川大学, 2005.

[2]郭敏杰.基于云计算的海量网络流量数据分析处理及关键算法研究[D].北京邮电大学, 2014.

C语言数组状态研究 篇3

关键词:C语言,数组,元素

1 整型数组状态分析

1.1 整型数组初始化后的状态分析

以下代码在定义一维整型数组时初始化部分元素, 并输出全部单元的值。

在编译系统下运行, 输出结果如下:

1 2 0 0

结果分析:对一维整型数组中的部分元素初始化, 未初始化的元素自动赋为0值。

以下代码在定义二维整型数组时初始化部分元素, 并输出全部单元的值。

输出结果如下:

结果分析:二维数组和多维数组从本质上来说, 就是一维数组, 只不过这类一维数组的每个元素也是一个数组而已。比如此二维数组实际是含有三个元素的一维数组, 每一行是它的一个元素, 每个元素又是一个一维数组。

1.2 给整型数组元素赋值后的状态分析

给整型数组中的部分元素赋值后, 对其他未赋值元素不产生影响, 保持原值。

1.3 输入数据给整型数组元素后的状态分析

为整型数组中的部分元素输入数据后, 对其他元素不产生影响, 保持原值。

2 浮点型数组状态分析

2.1 浮点型数组初始化后的状态分析

以下代码在定义一维浮点型数组时初始化部分元素, 并输出全部单元的值。

结果分析:对一维浮点型数组中的部分元素初始化, 未初始化的元素自动赋为0.000000, 这和整型数组类似。

2.2 给浮点型数组元素赋值后的状态分析

给浮点型数组中的部分元素赋值后, 对其他未赋值元素不产生影响, 保持原值。

2.3 输入数据给浮点型数组元素后的状态分析

为浮点型数组中的部分元素输入数据后, 对其他元素不产生影响, 保持原值。

3 字符数组状态分析

3.1 字符数组初始化后的状态分析

以下代码在定义一维字符数组时初始化部分元素, 并输出全部单元的值。

结果分析:对一维字符数组中的部分元素初始化, 未初始化的元素自动赋为空字符 (即'') 。需要说明的是, 在BC for Windows中用“¢”表示空字符, 而在BC for Dos中用空格代替输出的空字符。不同编译系统显示输出的空字符的方式有所不同。

3.2 给字符数组元素赋值后的状态分析

给字符数组中的部分元素赋值后, 对其他未赋值元素不产生影响, 保持原值。

3.3 输入数据给字符数组元素后的状态分析

为字符数组中的部分元素输入数据后, 对其他元素不产生影响, 保持原值。

值得注意的是, 在C语言中, 以字符''作为字符串的结束标志, 把字符串作为字符数组处理。在程序中根据''的位置判断字符串是否结束, 而和字符数组的长度无关。换句话说, 在字符数组中出现的第一个''之前的字符才是字符串中的有效字符。

以下代码用一个字符串常量对一维字符数组初始化, 而后向数组中输入另一个较短的字符串, 初始化和输入后都输出全部单元的值。

结果分析:虽然部分元素‘t’、‘e’、‘r’并未被输入的新串覆盖, 保持了原值, 但它们已不属于数组中存放的字符串 (即“good”) 的有效字符。

4 指针数组状态分析

4.1 指针数组初始化后的状态分析

以下代码在定义一维指针数组时初始化部分元素, 并输出全部单元的值。

结果分析:输出结果的前两个数是变量b、c的有效地址, 未初始化的元素自动赋为0值。

4.2 给指针数组元素赋值后的状态分析

给指针数组中的部分元素赋值后, 对其他未赋值元素不产生影响, 保持原值。

4.3 输入数据给指针数组元素后的状态分析

为指针数组中的部分元素输入数据后, 对其他元素不产生影响, 保持原值。

5 结构体数组状态分析

5.1 结构体数组初始化后的状态分析

以下代码在定义一维结构体数组时初始化部分元素, 并输出全部单元的值。

结果分析:对一维结构体数组中的部分元素初始化, 未初始化的元素的成员和前面提到的标准类型数组初始化的处理方式相同。如果只对第一个元素的部分成员初始化, 则此元素的未初始化成员以及其余未初始化的元素也类似处理。比如将以上代码第3行做如下修改:

5.2 给结构体数组元素赋值后的状态分析

给结构体数组中的部分元素或某个元素的部分成员赋值后, 对其他未赋值元素或这个元素的未赋值成员不产生影响, 保持原值。

5.3 输入数据给结构体数组元素后的状态分析

为结构体数组中的部分元素或某个元素的部分成员输入数据后, 对其余元素或这个元素的其余成员不产生影响, 保持原值。

参考文献

VB中控件数组及其应用 篇4

在开发Visual Basic 6.0的应用程序时, 往往要使用一些类型相同、功能相似的控件。如果对每一个控件都单独处理, 不免多做一些麻烦而重复的工作, 而且也会消耗更多的资源。这时可以将这种同一类型的控件定义成一个控件数组。例如, 可以将一组命令按钮定义成一个控件数组, 也可以将一组文本框定义成一个控件数组。控件数组为处理功能相近的控件提供了极大方便。

1 控件数组基本概念

控件数组是由一组相同类型的控件组成, 这些控件共用一个控件名称 (Name属性) , 具有相似的属性设置, 共享同样的事件过程。控件数组中各个控件相当于普通数组中的各个元素, 同一控件数组中各个控件的Index属性相当于普通数组中的下标。例如, 由一个包含3个单选按钮的控制数组Option1, 它的3个元素就是Option1 (0) 、Option1 (1) 、Option1 (2) 。

一个控件数组至少应有一个元素 (控件) , 元素数目可在系统资源和内存允许的范围内增加, 可用到的最大索引值为32 767。同一控件数组中的不同控件可以有自己的属性值设置。在建立控件数组时, 每个元素 (控件) 被自动赋予一个唯一的索引号 (Index属性, 相当于普通数组的下标) , 索引号从0开始, 通过索引号引用控件数组中的某个控件, 即控件数组名 (索引号) 。

使用控件数组的好处是: (1) 便于控件管理, 它们共用一个名称, 通过Index进行区分; (2) 运行期间可以添加控件, 使用控件数组添加控件所消耗的资源比直接向窗体添加多个相同类型的控件消耗的资源要少; (3) 控件数组中的不同控件共享相同的事件过程, 因为控件数组的事件可以共享, 如果要使多个同类型控件在一个事件中执行相同或类似的代码, 使用控件数组比单独创建多个控件更方便, 代码也更容易维护。

2 控件数组建立方法

控件数组中的每一个元素都是控件, 其定义方式与普通数组不同。可以在设计阶段创建控件数组, 也可以在运行期间动态创建控件数组。

2.1 在设计阶段创建控件数组

设计阶段可以通过以下两种方法创建控件数组:

(1) 复制现有控件, 将其粘贴到所在容器中。绘制或选择要作为控件数组的第1个控件, 执行“编辑|复制”命令, 选中容器, 再执行“编辑|粘贴”命令, 系统会给出一个对话框, 询问是否建立控件数组, 单击“是”按钮即可。绘制或选择的第1个控件的Index属性值为0, 新粘贴控件的Index属性值为1, 每个新数组元素的Index属性值与其添加到控件数组中的次序相同。用这种方法添加控件时, 大多数可视属性, 如高度、宽度和颜色等, 将从数组中的第1个控件复制到新控件中。

(2) 将窗体上已有类型相同的多个控件的Name属性设置为同一值。先选定一个控件作为数组的第1个元素, 并将其Name属性值设置成数组名 (或使用其原有的Name属性值) , 将其它同类型控件的Name属性值改成同一个名称。这时, 系统同样会询问是否建立控件数组, 选择“是”按钮将控件添加到控件数组中, 这样操作后, 控件数组中控件的Index属性值分别变成了0、1、2、…… (即控件数组元素的索引) 。用这种方法建立的控件数组元素仅仅具有相同的Name属性和控件类型, 其它属性与最初绘制控件时的值相同。

2.2 在运行期间创建控件数组

在运行时, 使用Load语句向现有控件数组中添加控件。通常设计时在窗体上创建一个Index属性为0的控件, 然后在运行时使用Load语句添加控件, Load语句格式如下:

Load控件数组名 (索引号)

例如, 假设已经在设计时建立了一个控件Option1 (0) , 在运行时可以用以下语句向控件数组中添加一个新的控件:

Load Option1 (1)

使用Load语句添加的控件数组元素, 其大多数属性值将由数组中具有最小下标的现有元素复制, 而且新添加的控件是不可见的, 必须编写代码将其Visible属性值设置为True, 通常还要调整其位置 (比如Top或Left属性的值) , 才可以在界面上显示出来。例如:

Option1 (1) .Visible=True

Option1 (1) .Top=500

Option1 (1) .Left=1000'Top或Left的值视情况而定

使用Unload语句可以删除在运行期间创建的控件数组元素, Unload语句的格式如下:

Unload控件数组名 (索引号)

例如, 要删除上面创建的Option1 (1) 控件, 可以使用语句:

Unload Option1 (1)

3 控件数组应用示例

通过以下几个示例, 介绍控件数组的应用。

例1:设置文字颜色。

在窗体上建立一个标签Label1和一个框架Frame1, 在框架Frame1中创建一个控件数组Option1 (0) ~Option1 (3) , 单击这4个单选按钮, 分别将标签Label1的文字颜色设置为“黑色”、“红色”、“蓝色”和“黄色”。

设计界面、运行界面分别如图1和如图2所示。

为实现题目功能的要求, 编写控件数组Option1的Click事件过程如下:

控件数组Option1包含4个单选按钮, 无论单击哪个单选按钮, 都将执行相同的事件过程。系统会将被单击的单选按钮的Index属性值传递给事件过程, 由事件过程根据不同的Index值执行不同的操作。

例2:使用控件数组创建电影胶片特效。

向窗体上添加一个Image控件Image1, 通过设置其Picture属性添加一幅图片, 调整好大小, 然后用复制、粘贴的方法创建一个控件数组Image1 (0) ~Image1 (3) 。添加一个Timer控件Timer1, 设置Timer1控件的Interval属性值为20。

设计界面、运行界面分别如图3和图4所示。

在窗体的Load事件过程中编写代码, 调整窗体的宽度和各图像框的初始位置, 使得运行初始时, 窗体宽度正好可以显示3幅水平并排的图片Image1 (0) -Image1 (2) , 使第4幅图片Image1 (3) 在窗体左侧的不可见区域, 其右侧与窗体左边界对齐。Load事件过程的代码如下:

通过定时器控制每隔20ms将各图像框向右移动20缇, 如果图像框的左侧已经大于窗体的内部宽度, 说明图像框已经移出窗体, 则将相应的图像框移回窗体左侧不可见区域, 使其右侧与窗体左边对齐。Timer1控件的Timer事件过程如下:

运行时, 各图片沿窗体左侧逐渐向右侧移动, 产生电影胶片的效果。

例3:控件的添加和删除。

在窗体上绘制一个复选框Check1, 将其Index属性值设置为0, 使其成为控件数组的第一个元素。再在窗体上添加3个命令按钮Command1、Command2和Command3, 分别实现添加控件、删除控件和关闭窗体的功能。

设n表示添加的控件数 (本例假设其最大值为3) , n应作为窗体级变量进行声明:

4 结语

控件数组提供了一种方便的控件组合方法, 这种组合控件的方法, 既可方便地对同类型控件进行管理, 又可使这些控件共享事件过程代码, 不仅代码编写高效, 而且代码也容易维护。

摘要:控件数组是一种方便组合同类型控件的方法, 这些控件具有共同的名称, 共享同一事件过程代码, 根据不同的Index属性值执行不同的处理程序段。在介绍控件数组基本概念及其建立方法的基础上, 着重研究了VB中控件数组的应用。控件数组不仅利于管理同类型控件, 而且可以优化程序代码。

关键词:Visual Basic,控件数组,Index属性值,共享事件代码

参考文献

[1]求是科技.Visual Basic 6.0程序设计与开发技术大全[M].北京:人民邮电出版社, 2004.

[2]王建忠.Visual Basic程序设计[M].北京:科学出版社, 2013.

数组技术 篇5

控件数组为使用共享公共功能的控件组提供了一种方便的方式。例如, 控件组可以用来显示相关数据, 或者在单击时提供相关的操作。控件数组处理多个控件统一事件上很方便此功能使得创建一个能够响应由多个不同控件引发的事件的处理程序方法成为可能。使用控件数组可开发出一些小型游戏。控件数组的灵活使用能够大大提高编程人员的编程效率。Delphi未提供专门的控件数组, 本文主要讨论的是如何在Delphi中模拟实现控件数组。

2、控件数组原理

标准的控件数组是由一组相同类型的控件组成。它们共用一个控件名, 具有相同的属性, 执行相似的操作, 同时共享同样的事件过程。为区分控件数组中的各个元素, 具有此功能的程序设计语言通常会把各元素的下标值传送给过程, 过程从接收到的下标来区分不同的元素。

3、Delphi中控件数组的模拟实现

3.1 Delphi模拟控件数组原理分析

VB是具有的灵活的控件数组功能的典型程序设计语言, 但在DELPHI中却未专门提供控件数组, 在很多DELPHI的教材中都提到一个方法:TLISTSTRING;使TLISTSTRING类控制容器中的控件以达到使用控件数组的目的;另外一种途径是由用户自己来开发带数组性质的VCL组件。这两种方法对DELPHI的是初级入门者是不现实的。使用TLISTSTRING类代码量大, 难以阅读, 使用时非常吃力;由用户自己制作组件这又不是DELPHI初级使用者所能完成的工作。在Delphi中, 各控件排列的先后顺序和它被拖放到窗体上的先后顺序相同。这个顺序是可以人为修改的, 通过修改这个顺序, 能够实现控件的数组化。

3.2 Delphi模拟控件数组模拟实现方案

使用Delphi窗体的Components[I], Component Count;Component Index三个属性模拟控件的数组化。各属性相关含义如下:

Components[I]属性表示当前窗体上所有属于T C o m p o nent类的对象形成的数组Component Count属性表示当前窗体上所有属于TComponent类的对象的个数Component Index属性表示当前窗体上属于TComponent类的某个对象在Components[I]数组中的下标

将窗体上所有Button组件的Caption属性设为Tbutton, 代码如下:

Var I:integer;

for I:=0 to component Count-1 do‘利用for循环判断某对象是否属于Tbutton类

分析:For循环用于遍历当前窗体上所有属于TComponent类的对象;if语句用于判断某个对象是否属于Tbutton类;如果条件成立, 则将该对象的Caption属性修改为'TButton'。通过上述分析, 不难发现, 这种方法有一定局限性, 最明显的是设计人员并不知道Components[I]到底代表哪一个控件, 因此只能用遍历的方法进行筛选, 这不仅影响了程序执行的效率, 也带来编程上的繁琐问题。

要解决上述问题, 就要用到TComponent类的Component Index属性。在delphi 7.0中, Component Index属性表示当前窗体上属于TComponent类的某个对象在Components[I]数组中的下标并且该属性是一个可读写属性;该属性的默认值是该组件的添加次序 (从0开始计数) , 那么就可以利用这一属性在组件生成时将同类组件的Component Index属性设置为连续的自然数数列;比如:n, n+1, n+2, ……, n+m;如果我们要修改窗体上的该类组件, 只需要遍历Components[I]数组的部分下标 (比如Components[n]……Components[n+m]) 就可以实现。从而提高程序执行效率, 同时也避免了编程上的繁琐问题。

实现方案如下:

例如:在窗体上添加若干个组件各组件布置如下图所示:

现修改四个Edit组件的Color属性为cl Red、Enabled属性为False、字体设为宋体。最简单的方法是逐句编写代码:

但如果Tedit组件数量很多并且要修改它的多个属性, 代码就变得很冗长。于是采用循环来实现。

实现方法如下:

第一步、要使所有要操作的Tedit组件的Component Index属性的值有序并连续。实现方法有两种:

方法一、窗体上各组件Component Index属性值与它被拖放到窗体上的先后顺序相同。一次把所有需要的TEdit组件依次加入窗体, 这样就可以实现所有Tedit组件的Component Index属性的值有序并连续;然后测试出最先加入窗体的TEdit组件的Componen t Index属性值。最后要说明的是:此后该窗体任何组件的Componen t Index属性值不能用代码修改。

方法二、在窗体生成时通过代码修改所有Tedit组件的Comp onent Index属性的值有序并连续。代码如下:

edit1.Component Index:=2;‘设置各Edit控件的Compo nent Index属性并使其连续

第二步、利用要操作组件Component Index属性的有序性和连续性编写循环程序用于实现窗体上所有TEdit组件的属性修改。程序代码如下:

实例中窗体上共有12个TComponent类组件, 即Components[I]数组共有12个Tcomponent类元素 (I的取值为0到11) , 通过我们上面第一步的调整使TEdit组件在Components[I]数组中的下标分别为2、3、4、5, 基于此我们可以知道:当I? (2, 5) 时, components[I]对象一定是TEdit类的实例, 因此我们就不用再判断components[I]对象是不是TEdit类的实例, 同时也不用再遍历、判断另外的的八个对象;这样不仅使程序的代码结构简洁, 而且使程序的运行速度提高了3~4倍。

4、结语

控件数组的灵活使用能够大大提高编程效率, 在Delphi中利用模拟控件数组弥补了Delphi中没有真正的控件数组这一缺憾, 使用该方法模拟实现的控件数组更加灵活, 其中的控件允许属于不同的类。在现代应用领域中控件数组有着广泛的应用, 其中在实现局域网中多个站点互连中显示了其独特的方便性。随着对软件优化度要求的提高, 控件数组也会有更广泛的使用。

摘要:利用窗体的Components[I], ComponentCount;ComponentIndex三个属性模拟实现控件的数组化。

关键词:Delphi,控件数组,Components[I]

参考文献

数组技术 篇6

数据立方体是一种多维数据模型, 支持感念分层, 可以通过上钻与下卷在不同的概念层次上查看数据, 主要用于O- LAP, 也可以用于高维数据挖掘。由于OLAP需要在大规模的数据仓库上执行复杂的操作, 为了缩短访问时间, 高效地分析数据, 一般要对数据立方体进行预计算, 也称为立方体物化。立方体物化是指在不同维组合上对基本单元进行聚集, 每次聚集会产生一个m维聚集单元, 所有在相同维组合上聚集产生的聚集单元组成一个m维方体。对于一个n维的数据立方体, 可以产生2n种不同的m维方体。立方体物化可以分为完全立方体、冰山立方体、 闭立方体和立方体外壳。其中完全立方体是指计算出数据立方体的所有不同的聚集单元, 可以完整反映数据立方体所蕴含的信息, 降低查询响应时间、提高联机分析处理的性能。对完全立方体的计算一般采用多路数组聚集技术, 下面介绍多路数组聚集技术。

多路数组聚集技术基本思想可以分为两部分: 首先将完整的数据立方体切分成多个块, 块大小要求可以完全放进内存进行计算, n维数据立方体的分块仍是n维数据立方体; 然后每次将一块子方体读入内存, 计算这个这个子方体的所有聚集单元; 根据读入数据块的顺序, 某些维度组合的聚集结果会被计算出来, 在所有块都被计算之后原始完全立方体的所有聚集单元就都已经计算完成。这种技术只对原始数据立方体进行一遍扫描, 就可以计算出所有的聚集单元, 可以有效地计算完全立方体, 但是随着数据量的增加和数据维度的增加, 在单机上运行该算法需要花费的时间和需要占用的内存空间都远远超出了用户的忍受范围。为了解决这些问题,有必要对算法进行并行化改造, 使其适应分布式计算环境, 下面介绍一种在大数据时代普遍使用的MapReduce分布式计算框架。

2 MapReduce 技术

MapReduce是一种编程模型 , 主要用于大规模数据集的并行计算, Map和Reduce分别指代映射和规约, 这两个函数需要用户自己定义, 并且以参数的形式传递给计算框架, 而对任务的分派和调度则由该计算框架完全自动处理或者在用户干预下自动处理, 使得用户可以简单地开发并行应用。简单地说, Map函数的作用是对用户输入的原始键值对进行初步处理, 产生中间键值对, 这些键值对会暂时储存在某些磁盘分区里; Reduce函数的作用是对调度程序指定的磁盘分区中的Map函数产生的中间键值对进行规约计算, 并产生最终结果。以词频统计为例, 用户要求是输入一组文章, 然后输出所有文章中出现的单词, 以及出现的频数; 使用MapRe- duce框架解决这个问题时 , 用户首先需要定义Map函数 : 接收文章, 并以键值对的方式返回文章中出现的单词和出现频数; 然后定义Reduce函数: 接收键值对, 进行合并之后返回最终的统计结果。定义了函数之后, 用户就可以将所有文章交给MapReduce框架处理, 计算框架会自动将输入文章划分为许多组, 然后交给多个计算节点并执行Map函数, 然后再将Map函数产生的中间键值对按照键的值进行聚集, 然后将每一组键值相同的键值对交个一个计算节点执行Reduce函数, 由Reduce函数输出最终结果。

用户所能做的事情除了定义Map和Reduce函数之外, 还可以指定Map函数与Reduce函数的个数, 以及通过以下接口干预应用的执行:

an input reader: 这个接口可以用来定义如何划分原始数据, 产生原始键值对。

aoutput writer: 这个接口可以定义如何将结果写入文件系统。

a combiner function: 这个函数相当于在本地对Map结果进行预处理, 目的是提高Reduce函数的效率。

a partition function: 这个函数用于指定将Map函数产生的中间结果存入哪个磁盘分区。

3 将 MapReduce 技术应用到多路数组计算

MapReduce就是通过控制一组计算机 , 对原始任务切分 , 并行计算, 然后并行规约得到最终结果的计算过程。可以看出, 这与多路数组聚集技术所使用的思想是相同的, 因此可以将MapReduce技术应用到多路数组计算中, 需要做的是设计Map函数和Reduce函数应该做什么, 以及对一些接口函数进行定义。

由于数据 立方体的 基础数据 结构是多 维数组 , 因此MapReduce计算框架在接收了完整的数据立方体之后 , 会按照系统默认值或者用户指定的值对数据立方体进行块划分, 然后将每个子方体储存在计算节点上等待计算。由于每个子方体也会使用多维数组储存, 在每个计算节点上数组每一维的起始下标都为零, 但是许多子方体在原始数据立方体的数组中的起始下标并不为零, 这就会导致Map函数产生的中间键值对的键的值与这个中间键值对应该有的键的值不符, 导致Reduce函数无法正常规约。因此需要一个长度与数据立方体维数相同的一维数组来记录一个子方体的每一维相对原始数据立方体的偏移量, 可以称之为偏移数组。用户可以通过对input reader接口进行定义, 将每个子方体对应的偏移数组和子方体组合成原始键值对传递给Map函数; 在Map函数产生了中间键值对之后, 可以在本地使用combiner函数使用偏移数组的值对中间键值对的键进行修正, 这样就可以保证re- duce函数产生正确的结果。对于Reduce函数的设计则比较简单, 与上文提到的词频统计应用相同。

下面以三维数据立方体为例说明上述过程: 如图1所示, 维A、B、C的基数都是4, 使用数组cube [4] [4] [4] 存储。定义每个子立方体的每一维的基数为2, 每个子方体用sub- cubei表示, 可以将原始数据立方体分为8块, 例如第一块由图1中编号为1,2,5,6,17,18,21,22的基本单元组成。定义每i个子方体的偏移数组为offseti, 通过input reader函数, 可以得到如下键值对:

定义通过Map函数处理之后, 中间键值对的键是聚集单元的描述, 形式是 (a,b,c), 其中a,b,c可以是数字或者“*”, 数字表示在相应维的下标, 对于〖subcube〗_1, a=0表示在A维的下标为0, “*”表示聚集维; 键值对的值是相应聚集单元的聚集值。这样对每个子方体进行Map处理后都会产生如下的键值对:

< (*,*,*) ,value>,< (*,*,0) ,value>,< (*,*,1) ,value>,< (*,0,*) ,value>,

……,< (0,0,*) ,value>,< (1,0,*) ,value>,……,< (0,0,0) ,value>.

以subcube2的< (1,0,*) ,value>为例, 键值 (1,0,*) 中a= 1, 代表在A维的下标为1, 但是实际下标应该是3。为解决这个问题使用combiner函数, 并利用原始键值对的键的值对这些中间键值对进行修正, 方法就是在中间键值对的键的值, 除了聚集维之外的每一维在原始值之上加上相应的偏移量。修正之 后subcube2的< (1,0,*) ,value>更改为subcube2的< (3,0,*) ,value>, 键表示的就与实际值相符了。

最后, 通过Reduce函数对中间键值对的键相同的那些键值对的value简单相加就可以得出每个聚集单元的最终值。

为了实现这个算法, 可以使用开源软件系统Hadoop来搭建分布式计算环境。Hadoop是实现了MapReduce技术的分布式软件框架, 通过这套软件系统, 可以将上述算法实现, 同时Hadoop开源社区还提供了例如Hive (数据仓库工具)、Pig (大数据分析平台) 等工具, 可以方便地对完全立方体计算的到的数据进行分析利用。

4 结语

基于容器对象的动态控件数组研究 篇7

动态数组[1]可以在运行期间改变数组大小,具有很强的灵活性,为开发者带来极大便利,广泛应用于各个领域[2,3]。动态控件数组就是一种特殊的动态数组,它的元素类型是控件类型。控件数组应该包含以下三个要素:

(1) 允许多个控件共享同一个事件句柄。即动态生成的多个同类型控件可以使用相同的事件名。这一点是BCB已经具备的功能。

(2) 可以在运行期间添加或者删除控件。BCB已经提供了这种机制。

(3) 可以方便地将多个控件组合为控件数组进行管理和使用。要组合控件最好的方法就是使用容器。BCB中能够实现控件数组的容器可以分为三种:第一种是VCL(Visual Componet Library,可视化组件库)中的TList类;第二种是VCL中的DynamicArray类;第三种是STL[4](Standard Template Library,标准模板库)中的Vector容器类。

文献[5]提出一种基于TList类的控件数组实现方法,在其基础上本文提出基于容器类的动态控件数组实现方案,并详细分析了其性能效率。

1 基于TList类的控件数组

1.1 VCL中的TList类

TList是VCL提供的一个用于维护对象列表的类,它是以链式存储指针的方式实现的。它存储了用于维护各种类指针的索引,这些索引存有指向各种对象的指针。为方便在对象列表中添加、删除、查找、访问、排序或者重组对象,TList提供了方便全面的链表功能,包括Capacity,Count,Items等主要属性和Add,Insert,Delete,Clear,First,Last等主要方法,各属性和方法详细信息如表1所示。

1.2 基于TList类的控件数组的实现思想

文献[5]提出一种基于TList类的控件数组实现方案,下面简要阐述其基本思想。

定义TList类型指针对象,建立控件数组CList,并调用构造函数对其进行初始化:

TList *CList = new TList() ;

动态生成控件对象Button,添加到CList中:

为Button声明并自定义事件MBClick,让所有动态生成的控件共享事件句柄:

通过TList对象的Items属性访问CList中的对象,甚至可以在自定义事件中访问TList对象中动态生成的控件:

删除CList中指定成员对象(第i个)时,先将CList中该成员对象的类指针索引装入临时指针,然后删除临时指针所指对象,同时删除控件数组中的指针记录:

清空整个CList时,先删除其中所有成员对象,再用Clear方法清空。程序结束时CList需要销毁,可在窗体的析构函数中加入以下代码:

2 基于DynamicArray模板的控件数组

2.1 VCL中的DynamicArray模板类

DynamicArray是VCL提供的一个用于实现变长动态数组的模板类[6],使用二进制数据块兼容Object Pascal动态数组实现。DynamicArray也可以看作是一个可以存放各种控件对象的容器,只需将动态数组声明中的数据类型设置为相应控件类型即可。为方便管理动态数组,DynamicArray模板提供了Length,High,Low等属性和Copy,CopyRange等方法,并重载了赋值运算符“=”、比较运算符“==”和访问数组元素的“[]”运算符,如表2所示。

2.2 基于DynamicArray模板的控件数组实现思想

利用DynamicArray模板实现动态控件数组时,需要将动态数组的类型设置为某一控件类型,通过在程序中动态修改动态数组的Length属性来实现数组大小的动态变化。下面以动态按钮数组(BArray)为例,详细说明动态控件数组实现思想。

声明动态按钮数组:

DynamicArray BArray ;

动态地向BArray中添加成员对象时,先将BArray的Length属性增加1,以便为待添加的新对象预留空间:

BArray.Length = BArray.Length + 1 ;

创建待添加的控件对象并装入新开辟的空间:

BArray[BArray.High] = (new TButton(this)) ;

获取新添加的控件对象:

TButton* Button = BArray[BArray.High] ;

删除指定成员(比如第i个)对象时,先删除动态数组中第i个成员对象:

delete BArray[i] ;

然后使用循环语句将被删除成员对象后面的元素全部前移:

最后将BArray的Length属性减少1:

BArray.Length = BArray.Length - 1 ;

如果要清空动态数组BArray中的所有成员,先要使用循环语句逐一删除BArray中的所有元素:

然后将动态数组BArray的Length属性设置为0,但无需使用delete语句销毁BArray:

BArray.Length = 0 ;

3 基于Vector容器类的控件数组

3.1 STL中的Vector容器类

Vector是STL容器类中最简单的容器类,通常也是效率最高的容器类。Vector[7]是一个随机存取的Sequence容器,采用连续的内存空间存放数据。它支持常数时间的尾部插入和删除、线性时间的其他位置的插入和删除。Vector模板类class vector接口成员(public)如表3所示。

3.2 基于Vector容器类的控件数组的实现思想

基于Vector容器实现动态控件数组的思想[8],将Vector中元素类型设置为相应的控件类型,然后利用Vector提供的push_back或insert方法,将动态生成的控件对象装入容器中,利用Vector提供的访问容器中元素的方法访问成员对象,或者利用Vector提供的pop_back或erase方法删除容器中的元素。下面还是以动态按钮数组(BVec)为例,详细说明基于Vector的动态控件数组实现过程。

定义相应类型(比如TButton)的Vector容器:

vector BVec ;

创建Button控件对象,然后添加到容器中:

BVec.push_back(new TButton(this)) ;

获取刚加入的控件对象指针,方便后续访问:

TButton* Button = *(BVec.end() - 1) ;

在删除容器中指定的元素(比如第i个元素)时,先要删除容器中该成员对象的类指针所指的对象,然后清除容器中该成员对象的值:

清空容器时先删除容器中所有成员的类指针所指的对象,这一点可以通过定义一个迭代器并遍历容器所有元素来实现。然后再清除容器中所有元素的值:

4 基于容器对象的动态控件数组性能分析

4.1 基于TList类的控件数组性能分析

基于TList类的控件数组应用广泛[9,10],实现方法简单,添加或删除对象方便而高效。但是这种方法存在以下4个方面的缺陷。

安全性问题

TList类本身就是一个缺乏类型安全支持的类。从其Add方法原型int_fastcall Add(void * Item)可以看出,TList对象存储并维护的是void*空指针。但是BCB编译器会将Add函数接收到的任何类型的指针转换为void*类型,而不做任何类型检查。同时,在引用控件数组中的一个对象时,需要将一个void*类型的指针强制转换为相应控件类型的指针。如果控件数组包含多种类型的成员控件,这时就无法确定空指针该强制转换为哪种类型的指针。一旦类型转换错误,那么在访问成员控件时就会产生严重的问题。

内存空间释放问题

一方面,TList不能自动删除列表中的指针;另一方面,由于列表中的指针是空指针,删除空指针的时候不会调用析构器中的析构函数,那么就无法释放内存空间,从而造成内存泄露。

效率问题

实验表明,当TList存储5 000个以上对象时,效率就会大幅下降。

移植性问题

由于BCB的VCL完全是用Object Pascal语言编的,使得BCB同时获得了Pascal和C++的强大功能,同时可移植性就很差。

4.2 基于DynamicArray类的控件数组性能分析

用DynamicArray实现控件数组,原理简单、代码简洁,不存在类型安全和内存释放问题。但是,DynamicArray使用二进制数据块兼容Object Pascal动态数组实现,这会带来系统瓶颈,严重影响运行效率。DynamicArray的空间扩充机制也不尽完美。当数组长度超过固定大小时,就会频繁地重新申请内存空间,并将原来内存空间中的二进制数据块拷贝到新申请的内存空间中,然后将原空间释放掉,这就会大大降低运行效率。特别是如果二进制数据块比较大的时候,系统瓶颈尤其突出。另外,由于DynamicArray是VCL中的模板类,故移植性较差。

4.3 基于Vector容器类的控件数组性能分析

Vector采用线性连续的内存空间存放数据,因而随机访问数组元素和Vector尾部插入元素效率很高,但是在任意位置插入元素的效率比较低。为了提高效率,Vector使用了自增长机制,实际上就是运用动态弹性内存空间[8],随着新元素的加入,自行扩充内存空间。为了合理控制空间大小、提高重新配置空间时的效率,Vector 实际配置的空间比需求空间大一些,以备将来可能的扩充。向Vector中插入元素时,首先考虑备用空间是否足够,如果够就插入到备用空间,否则,重新配置双倍于现在容量的内存空间,然后将原来的数据拷贝到新空间中,最后释放原内存空间。在控件数组中元素个数不超过1 000万个时,Vector的空间扩充方式效率都是很高的。Vector的空间扩充过程如图1所示。

另外,当容器内元素操作比较复杂时,Vector效率不佳。

5 结 语

BCB是一个优秀的应用程序开发平台,其提供的VCL库更是为开发者带来了极大便利。VCL提供的TList和DynamicArray都可以很容易地实现动态控件数组。但是,TList缺乏类型安全支持,而且Dynamic-Array也存在系统瓶颈问题,而且移植性都比较差,因此它们适合于小规模的局部应用的动态控件数组中。而标准模板库STL提供的容器类Vector具有完备的类型安全机制,移植性比较好,执行效率也相对很高,但是在支持数组元素复杂操作方面欠佳,故这种方法适合于较大规模的通用动态控件数组中。总之,没有哪种方法一定是最好的,具体采用什么方法要根据问题规模、应用范围等因素来决定。

参考文献

[1]陈凤祥,李汪根.C++动态数组的实现与重用[J].计算机技术与发展,2010,20(2):79-82.

[2]孙桂娟,张庆明,郑全平,等.基于可变数组管理方法的震塌破坏数值仿真[J].北京理工大学学报,2009,29(6):492-496.

[3]乔平安.动态统计图控件的设计与实现[J].现代电子技术,2006,29(6):118-120.

[4]葛建芳.C++标准模板库与代码重用[J].南通大学学报:自然科学版,2006,5(2):71-74.

[5]许天然.在C++Builder中实现控件数组[J].琼州大学学报,2006,13(5):27-29.

[6]周熙,汪红.C++Builder环境下MVC框架结构的应用[J].中南民族大学学报:自然科学版,2007,26(2):87-89.

[7]宫护震,史云鹏,孙吉赟.一种基于STL(标准模板库)的三维数据可视化容器设计[J].现代电子技术,2007,30(22):80-81.

[8]帖军,王小荣,金佳.移动实时环境下的数据一致性研究[J].中南民族大学学报:自然科学版,2011,30(2):92-95..

[9]景春国,舒冬梅.TList对象在监控软件数据点的内存管理和处理方面的应用[J].现代电子技术,2003,26(2):7-12.

上一篇:故事拓展下一篇:小型商业网站建设