第五章 数组 5.1 数组的概念 5.2 数组的基本操作 5.3 数组举例 5.4 动态数组 5.5 程序示例及相关算法
5.1 数组的概念 数组是一组具有相同类型的有序变量的集合;数组的结构 使用数组就是用一个相同的名字引用这一组变量中的数据,这个名字称为数组名。 数组说明 数组的结构 数组函数及数组语句
数组说明语句 数组说明语句格式: Public|Private|Static |Dim<数组名>([<维界定义>] )[As <数据类型>] <维界定义>的格式为: [<下界1> to] 上界1[[<下界2> to 上界2……] 其中“下界”和 “to”可以省略,此时等价于“0 to 上界” ,如程序中使用了 Option Base 1,则等价于 “1 to 上界
数组的上、下界 数组的上、下界概念: 某维的下界和上界分别表示该维的最小和最大的下标值。 维界的取值为长整型数据范围,且下界≤上界,在定义固定大小数组时,维的上、下界说明必须时常数表达式,不可以是变量名。如果维界说明不是整数,VB将对其四舍五入处理。
数组的类型 与变量类似,数组类型也可以是Integer、Long 、Single 、Double 、Date 、Boolean 、String 、 String *length 、Object 、Currency 、Varint和自定义类型。缺省时为变体类型。
数组的大小 数组的大小=第一维大小×第二维大小×…×第n维大小 维的大小=维上界-维下界+1 数组定义举例: Option Base 1 Dim A(2*3) ,b(-1 to 3.5 , 4) As integer A数组为变体类型,大小=2*3-1+1=6 B数组为整型类型,大小=(4-(-1)+1)*(4-1+1)=24 两数组均为模块级数组。
5.1.3数组的结构 一维数组的结构 二维数组的结构 三维数组的结构
一维数组的结构 一维数组的定义: Dim A(5) 数组A的逻辑结构: A(5)=(A(0), A(1), A(2), A(3), A(4), A(5)) 一维数组在内存中的存放次序: A(0) A(1) A(2) A(3) A(4) A(5)
二维数组的结构 二维数组是由行、列组成的二维表,二维数组的元素是由行号、列号来标识的。 定义数组: Dim B(2,3) 数组B的逻辑结构: B(0,0) B(0,1) B(0,2) B(0,3) B(2,3)=B(1,0) B(1,1) B(1,2) B(1,3) B(2,0) B(2,1) B(2,2) B(2,3) 二维数组在内存中的存放次序:“按列存放”,既先存放第一列的所有元素,接着再放第二列 所有元素... ...
三维数组的结构 三维数组是由行、列、页组成的三维表,其可理解为几页的二维表,三维数组的元素是由行号、列号、页号来标识的。 定义数组: Option base 1 Dim C(3,3,2) 数组C的逻辑结构: C(1,1,1) C(1,2,1) C(1,3,1) 第 C(1,1,2) C(1,2,2) C(1,3,2) 第 C(2,3,2)=C(2,1,1) C(2,2,1) C(2,3,1) 一 C(2,1,2) C(2,2,2) C(2,3,2) 二 C(3,1,1) C(3,2,1) C(3,3,1) 页 C(3,1,2) C(3,2,2) C(3,3,2) 页 三维数组在内存中的存放次序:“逐页存放”,既先对数组的第一页中的所有元素按列的顺序分配存储单元,然后再第二页中的所有元素按列的顺序分配存储单元 ... ...
5.1.4数组函数及数组语句 Lbound函数 功能:返回数组某维的维下界的值。 格式: Lbound(name,[,d]) Ubound函数 功能:返回数组某维的维上界的值。 格式: Ubound(name,[,d]) d为维数,缺省时函数返回数组第一维的维上界
5.1.4数组函数及数组语句(续) Erase语句 功能:重新初始化固定大小数组的元素,或者 释放动态数组的存储空间。 功能:重新初始化固定大小数组的元素,或者 释放动态数组的存储空间。 格式: Erase a1[,a2,... ...] 其中a1、a2为需要重新初始化的数组名。
Erase语句例题 Dim a(3) as integer,B( ) as integer a(1)=1: a(2)=2: a(3)=3 Private Sub Form_Click() Dim a(3) as integer,B( ) as integer a(1)=1: a(2)=2: a(3)=3 ReDim b(4) Print a(1), a(2), a(3) Erase A,B End Sub Erase语句执行后,整型数组a的所有元素值将改变为0;分配给动态数组b的8个字节的存储单元释放给系统,b数组又成为一个没有存储单元的空数组。
5.2 数组的基本操作 数组元素的本质仍是变量,只是带有下标的变量,但是,数组元素是有序的,可以通过改变下标访问不同的数组元素,因此利用循环处理整个数组或数组中连续的元素是最有效的方法。 数组元素的赋值 数组元素的输出 For Each-Next 结构语句
数组的输入 用赋值语句给数组元素赋值 通过循环逐一给数组元素赋值 用InputBox函数给数组元素赋值 用Array函数给数组赋值
用赋值语句给数组元素赋值 通过赋值语句给单个数组元素赋值。 Dim a(3) As Integer ,b(2, 2) As Integer b(0,2)=b(0,1) ... ...
通过循环逐一给数组元素赋值 Dim a(3) as integer , i as Integer For i=0 to 3 a(i)=Int(99*Rnd)+1 Print a(i); Next i Print 注意:给一维数组赋值用一重循环实现,给二维数组赋值用双重循环,依次类推
用InputBox函数给数组元素赋值 Dim a(6) as integer,I as integer For i=0 to 6 a(i)=Inputbox(“给数组元素赋值”,“数组a赋值”) Print a(i); Next i
用Array函数给数组赋值 格式:<变体变量名>=Array([数据列表]) 功能:将一个数据集赋值给一个Variant 变量创建成一个一维数组。 <数据列表>是用逗号分隔的赋给数组的各元素的值
几个注意点 1、Array 函数只能给Variant 类型的变量赋值。 2、创建的数组的长度与列表中的数据的个数相同。 3、若缺省<数据列表>,则创建一个长度为0的数组。 Array 函数创建的数据的下界默认从0开始,若使用了Option Base 1语句,则数组的下界从1开始。 4、 Array 函数只能生成一维数组 5、允许多次用Array 函数生成不同类型的同名一维数组。
用Array函数给数组赋值 Private Sub Form_Click() Dim a As Variant, b(4) As Variant a = Array(5, 4, 3, 2, 1) Print a(0); a(1); a(2); a(3); a(4) a = Array(1.5!, 2.3!, 3.6!, 4.1!) Print a(0); a(1); a(2); a(3) a = "no array" Print a b = Array(1, 2, 3, 4, 5, 6) End Sub
数组元素的输出 可以使用Print方法将数组元素显示在窗体上或者显示在Picturebox中,也可以显示到文本框中。 与输入相似,可以利用循环控制数组元素的输出。
数组元素的输出 用随机函数产生两位整数给一个3行*4列的数组赋值,并在当前窗体上显示。 Dim A(2,3) as integer,i as integer,j as integer For i=1 to 2 For j=1 to 3 A(i,j)=Int(Rnd*90)+10 Print A(i,j); Next j Print Next i
For Each-Next 结构语句 格式:For Each 变体变量 In <array>|<object set> [语句组] [Exit For] Next [变体变量] 功能:此语句是专门用来为数组或对象集合中的每个元素重复执行一组语句而设置的。程序执行该语句时,VB跟踪必须处理的元素的总数,处理每一个元素,并在到达数组或集合末尾时会自动停止循环。
For Each-Next 结构语句格式说明 格式中的Variant变量实际上代表的是数组中每一个元素或对象集合中的每一个成员。 <array>是要处理的数组名。<object set>是这个循环要处理的对象集合名。一个For Each-Next 结构中只能处理两者中的一种。 循环次数由数组中的元素个数或对象集合中的成员个数确定。
For Each-Next 结构语句举例 Option Base 1 Private Sub Form_Click() Dim A(8) as integer,V as Variant Dim i as integer,js as integer js=14 For i=1 To 8 A(i)=JS JS=JS+7 Next i For Each V In A Print V; Next V End Sub
数组举例 随机生成两位正整数构成的一维数组a(12),找出其中的最大数和最小数。 分析: 这是求最大值和最小值的程序,可按相关的算法思想完成程序的设计。 定义两个变量max和min分别存放最大值和最小值。
数组举例 Private Sub Form_Click() Dim i As Integer, a(12) As Integer Dim max As Integer, min As Integer For i = 1 To 12 a(i) = Int(Rnd * 90) + 10 ‘随机生成两位正整数 Print a(i); Next i Print
数组举例 max = a(1): min = a(1) For i = 2 To 12 If a(i) > max Then max = a(i) ‘最大值 ElseIf a(i) < min Then min = a(i) ‘最小值 End If Next i Print "最大数是:"; max, "最小数是:"; min End Sub 如何求二维数组的最大值和最小值(位置) 如何求 二维数组的鞍点元素
5.3 动态数组 当编写程序时不能确定数组的大小时,可考虑定义数组为动态数组。 动态数组的定义分为2步: 1、在标准模块、窗体模块层或过程中使用下面语句定义不指明大小的数组。 Public|Private|Dim |Static 数组名( ) [As 数据类型] 2、使用前用ReDim 语句重新定义数组的大小、分配存储空间。 ReDim [Preserve] 数组名(维界定义)[As 数组类型]
动态数组定义说明 1、动态数组在使用前必须用Redim 重新定义 2、ReDim 语句是一个可执行语句,只能出现在过程中。 3、重新定义动态数组时,不能改变数组的数据类型,除非是Variant变量所包含的数组。 4、重新定义动态数组时,可以用变量说明动态数组的大小。 5、语句中若缺省Preserve,可以重新定义动态数组的维数和各维的上、下界,执行ReDim 语句时,当前存储在的数组中的值全部丢失,重新定义的数组被赋予该类型变量的初始值。若要保留原数组内容,应使用Preserve,并只能改变最后一维的维上界。 6、若ReDim 语句所使用的数组不存在,系统会动态创建一个新数组并给数组分配存储空间。
动态数组举例 Private Sub Form_Click() Dim a( ) As Integer, x As Integer, y As Integer ReDim a(2) a(0) = 33: a(1) = 44 Print a(0); a(1); a(2) ReDim Preserve a(3) a(2) = 55: a(3) = 66 Print a(0); a(1); a(2); a(3) x = 4: ReDim a(x) a(x) = 77 Print a(0); a(1); a(2); a(3); a(4) x = 2: y = 3 ReDim a(x, y) End Sub 在窗体上显示结果: 33 44 0 33 44 55 66 0 0 0 0 77
动态数组的应用 编程求出所有1000以内的素数,并按一行10个输出在窗体上。
数组程序示例与常用算法 相关考题 程序示例 数组常用算法
考题(一) 以下有关数组的说明中,错误的是: A、根据数组的说明,可将数组分为动态数组和静态数组 B、在过程中,不能用Private语句定义数组 C、利用Redim语句重新定义维界,不得改变已经定义说明过的数组的数据类型 D、数组重新定维后,原有的数组元素内容将不予保留
考题(二) 下列关于数组的叙述中,错误的是: A、数组是同类变量的一个有序集合 B、数组元素可以是控件 C、数组在使用之前,必须先用数组说明语句进行说明 D、数组在定义时若不能确定大小,数组的维界可以使用变量
考题(三) 在窗体的通用声明段处有语句Dim a( ) as Single,以下在某事件过程中重定义此数组的一组正确语句是: B、 Redim a(3,3) Redim Preserve a(4,4) A、Redim a(3,3) Redim a(4,4) as Integer D、Redim a(3,3) Redim Preserve a(3,4) C、Redim a(3,3) Redim a(3,3) as Integer
考题(四) 下面有关数组处理的叙述中,不正确的是 ① 在过程中用Redim语句定义的动态数组,其下标的上下界可为赋了值的变量 ② 在过程中,可以使用Dim、Private和Static语句定义数组 ③ 用Redim语句重新定义动态数组时,不得改变该数组的数据类型 ④ 可用Public语句在窗体模块的通用声明段定义一个全局数组 A、 ① ② ③ ④ B、 ① ③ ④ C、 ① ② ③ D、 ② ④
考题(五) 以下有关控件数组的说法中错误的是 A、控件数组由一组具有共同名称和相同类型的控件组成 B、控件数组中的每一个控件共享同样的事件过程 C、控件数组中的每个元素的下标由控件的Index属性指定 D、同一控件数组中的元素只能有相同的属性设置值
统计算法的应用 统计字母(不分大小写)在文本中出现的次数 分析: 这是典型的统计算法的程序,统计26个字母中每个字母在文本中出现的次数,所以可考虑定义26个计数器(数组A(0 to 25))。 Ch: A B C …… Y Z 考虑根据对应的计数器如何得到对应的字符 数组A: j =Asc(ch)-Asc(“A”) A(j)=A(j)+1
程序界面
统计算法的应用 UCase(Mid(st, i, 1)) j = Asc(ch) - Asc("A") a(j) = a(j) + 1 Private Sub Command1_Click() Dim st As String, j As Integer Dim a(0 To 25) As Integer Dim i As Integer, js As Integer, ch As String * 1 st = Text1.Text For i = 1 To Len(st) ch = If ch >= "A" And ch <= "Z" Then End If UCase(Mid(st, i, 1)) j = Asc(ch) - Asc("A") a(j) = a(j) + 1
统计算法的应用 Next i For i = 0 To 25 If a(i) < > 0 Then js = js + 1 Text2 = End If End Sub Text2 & Chr(i + Asc("A")) & “:" & a(i) & " " If js Mod 5 = 0 Then Text2 = Text2 & Chr(13) & Chr(10)
数组常用算法 排序 查找 插入 删除
排序 选择法排序 冒泡排序法
选择法排序过程 设有一个数组 a(5) (按从小到大的顺序排序) 65 54 34 23 12 由演示过程可以看出: 65 54 34 23 12 由演示过程可以看出: 5个元素的数组的排序需要经过4轮的比较,每一轮循环得到一个当前的最小元素
选择法排序算法思想 对有n个数的数组a(n) 第一轮:a(1)分别与a(2)、a(3)……a(n)进行比较,只要a(1)比任一个a(i)的值大,就交换a(1)与a(i)的值,最后在a(1)中存放最小值 第二轮:a(2)分别与a(3)、a(4)……a(n)进行比较,只要a(2)比任一个a(i)的值大,就交换a(2)与a(i)的值,最后在a(2)存放当前最小值 …… 第n-1轮:a(n-1) 与a(n)进行比较,只要a(n-1)比a(n)的值大,就交换a(n-1)与a(n)的值,最后在a(n-1)存放当前最小值
选择法排序应用 随机生成两位正整数的一维数组a(10),将数组元素按从小到大的顺序排序。 分析: 10 个元素的排序需要9轮的比较(i=1 ……9) I=1 时 a(1)与a(2)、a(3)……a(10)逐个比较 I=2 时 a(2)与a(3)、a(4)……a(10)逐个比较 I=9 时 a(9)与a(10) 比较 i:1到9 j:i+1 到10 …… 在每一轮的比较中都是 a(i) 和 a(j) 进行比较
选择法排序应用 Private Sub Form_click() Dim a(10) As Integer, i As Integer, j As Integer Randomize Print "排序前:" For i = 1 To 10 a(i) = Int(Rnd * 90) + 10 ‘生成两位随机整数 Print a(i) ; ‘输出排序前的数组元素 Next i Print Print "排序后:"
选择法排序应用 9 i + 1 10 a(i) > a(j) 选择法排序中数据交换的操作较多,如何改进? For i = 1 To For j = To If Then temp = a(i) : a(i) = a(j) ‘ 交换a(i)与a(j)的值 a(j) = temp End If Next j Next i For i = 1 To 10 Print a(i) ; ‘输出排序后的数组元素 Next I:End Sub 9 i + 1 10 a(i) > a(j) 选择法排序中数据交换的操作较多,如何改进?
改进的选择法排序 设有一个数组 a(5) (按从小到大的顺序排序) 65 54 34 23 12 由演示过程可以看出: 65 54 34 23 12 由演示过程可以看出: 5个元素的数组的排序需要经过4轮的比较,每一轮循环中最多执行一次交换操作,得到一个当前的最小元素
优化选择法排序的程序段 For i = 1 To 9 k=i For j = i + 1 To 10 If a(k) > a(j) Then k=j next j If i <>k then temp = a(i) a(i) = a(k) a(k) = temp End If Next i
冒泡法排序算法思想 对有n个数的数组a(n) 第一轮:a(1) 与a(2)、a(2)与a(3) …… a(n-1) 与a(n)相邻元素进行比较,只要前一个数比后一个数大,就交换相邻元素的值,最后在a(n)中存放最大值 第二轮:a(1) 与a(2)、a(2)与a(3) …… a(n-2) 与a(n-1)相邻元素进行比较,只要前一个数比后一个数大,就交换相邻元素的值,最后在a(n-1)中存放最大值 …… 第n-1轮:a(1) 与a(2)进行比较,只要a(1)比a(2)的值大,就交换a(1)与a(2)的值,最后在a(2)存放当前最大值
冒泡法排序过程 设有一个数组 a(5) (按从小到大的顺序排序) 65 54 34 23 12 由演示过程可以看出: 65 54 34 23 12 由演示过程可以看出: 5个元素的数组的排序需要经过4轮的比较,每一轮循环中都是相邻元素进行比较,大数向后移,最后得到一个当前的最大元素
冒泡法排序应用 I=1 时 a(1)与a(2) 、a(2)与a(3)…a(9)与a(10)比较 i:1到9 分析: 10 个元素的排序需要9轮的比较(i=1 ……9) I=1 时 a(1)与a(2) 、a(2)与a(3)…a(9)与a(10)比较 i:1到9 I=2 时 a(1)与a(2)、 a(2)与a(3)…a(8)与a(9)比较 …… I=9 时 a(1)与a(2) 比较 j:1 到10-i 在每一轮的比较中都是 a(j) 和 a(j+1) 进行比较
冒泡法排序的程序段 1 To 9 1 To 10 - i a(j) > a(j + 1) a( j ) = a( j + 1) For i = For j = If Then temp = a( j ) a(j + 1) = temp End If Next j Next i 1 To 9 1 To 10 - i a(j) > a(j + 1) a( j ) = a( j + 1)
查找 顺序查找 二分法查找
顺序查找应用举例 从键盘上输入数值X,在已知数组中查找X,若找到,给出X在数组中所在的位置;若找不到,给出“找不到”的信息。 分析:
程序界面
顺序查找应用举例 Dim a(10) As Integer Private Sub Command1_Click( ) ‘生成数组 Dim i As Integer For i = 1 To 10 a(i) = Int(Rnd * 90) + 10 Text1.Text = Next i End Sub Text1.Text & a(i) & " "
顺序查找应用举例 Exit For i <= 10 “要查找的数” & x & "在a(" & i & “)中" Private Sub Command2_Click( ) Dim x As Integer, i As Integer x = InputBox("请输入要查找的数") For i = 1 To 10 If a(i) = x Then Next i If Then Text2= Else Text2= “要查找的数” & x & "不在数组a中" End If :End Sub Exit For i <= 10 “要查找的数” & x & "在a(" & i & “)中"
二分法查找的算法思想 二分法查找是针对有序数组执行的快速查找方法。 设一个有n个元素的有序数组a(按从小到大的顺序),下标从1到n 设用变量left表示查找区间的下界(1) 用变量right表示查找区间的上界(n) 用变量mid表示查找区间的中部位置 mid= (left+right)/2
二分法查找的算法思想 1、计算出中间位置mid,判断要查找的数x与a(mid)是否相等,若相等,表示已找到 2、如果 x >a(mid),说明x在区间的右边,让left =mid+1 3、如果 x <a(mid) ,说明x在区间的左边,让 right=mid+1 4、重复上述步骤,每次查找区间缩小一半,直到找到x 或left > right为止
二分法查找的过程 设有一个数组 a(10) 12 26 34 47 59 65 74 82 92 98 由演示过程可以看出: 12 26 34 47 59 65 74 82 92 98 由演示过程可以看出: 利用二分法查找数组元素,每次查找区间的中点,根据该点元素与x的关系进一步缩小查找的区间,直到找到或区间的下界大于上界为止
二分法查找的程序段 mid=(right+left)/2 If x=a(mid) then exit do 两个问题 ElseIf x > a(mid) then left=mid+1 Else right=mid-1 EndIf 两个问题 1、循环何时结束 2、调出循环后如何判断查找的结果
插入 在一个有序的数组中插入一个数,使插入后数组仍然有序。(从小到大) 分析: 1、查找插入的位置 不断的与要插入的数进行比较 2、在指定的位置上插入数
插入的程序段 Dim a(10) As Integer, x As Integer For i = 1 To 9 a(i) = i * 2 + 1 Print a(i); Next i Print x = InputBox(“输入要插入的数")
插入的程序段 For i = 9 To 1 Step -1 If x > a(i) Then Else Exit For End If Next i 考虑一下还有什么方法实现插入 Exit For a(i + 1) = a(i) a(i + 1) = x
插入的程序段 For i = 1 To 9 If x < a(i) Then Exit For Next i For j = 9 To i Step -1 a(j + 1) = a(j) Next j a(i) = x
删除程序示例 将一个数列中的重复数删除掉 分析: 1、对每个数,和剩下的所有数逐个进行比较,如果发现相同,就将相同的数删除掉 2、如何实现将数组中的一个数删除掉
删除程序段 设数组元素已赋给动态数组a Else ub = UBound(a) i = i + 1 n = 1 End If Do While n <= ub i = n + 1 Do While i <= ub If a(n) = a(i) Then For j = i To ub - 1 a(j) = a(j + 1) Next j ub = ub - 1 ReDim Preserve a(ub) Else i = i + 1 End If Loop n = n + 1 本题能否用for –Next循环完成?