第二章算法的程序实现
[
考试标准]
考试内容考试要求考试属性
1.枚举算法及程序实现 c
加试
2.解析算法及程序实现 c
3.排序算法及程序实现
(1)冒泡排序
(2)选择排序
c
4.查找算法及程序实现
(1)顺序查找
(2)对分查找
c
5.递归算法 a
6.VB访问Access数据库
(1)通过ADO对象连接数据库
(2)通过Recordset对象获取数据表中的数
据
a
一、排序算法及程序实现
1.排序的含义及方式
(1)所谓排序就是将无序的数列变成有序的数列。
(2)排列方式分为升序(也称递增,即从小到大排列)和降序(也称递减,即从大到小排列)。
2.冒泡排序
(一)算法基本思想
冒泡排序法第i遍排序是从第n个数(从后向前比较)或者第1个数(从前向后比较)开始,依次比较相邻的两个数,逆序时交换两个数,把第i个有序的数交换到第i个或者第n-i+1个位置。
数据的交换是在内层循环中发生。
(二)核心代码
①将数组a(1 to n)从大到小排序,从后向前比较
For i=1 To n-1
For j=n To i+1 Step-1
If d(j-1) t=d(j):d(j)=d(j-1):d(j-1)=t End If Next j Next i ②将数组a(1 to n)从大到小排序,从后向前比较 For i=1 To n-1 For j=1 To n-i If d(j) t=d(j):d(j)=d(j+1):d(j+1)=t End If Next j Next i 3.选择排序 (1)选择排序的基本思想 每趟排序是在所有的数据中找出最小(或最大)的数据,使它与第一个数据相互交换位置,然后再在剩下的数据中找出最小(或最大)的数据,与第二个数据相互交换位置,以此类推,直到所有元素成为一个有序序列。 (2)选择排序的程序实现 说明:要排序的n个数据已存放d数组中。 以升序为例的程序如下: For i=1 To n-1′n个排序共进行n-1趟排序 k=i′第i趟排序时,首先用k记录i For j=i+1 To n′k位置上的数依次与j位置上的数进行比较 If d(k)>d(j)Then k=j′若找到比k位置上更小的数,则更新k的值 Next j If k<>i Then′若i位置上的数不是最小数,则和k位置上的数进行互换 temp=d(i) d(i)=d(k) d(k)=temp End If Next i 温馨提示:若要按降序排列,只要将语句If d(k)>d(j) Then k=j改成If d(k)<d(j) Then k=j即可。 二、查找算法及程序实现 1.查找算法 所谓查找就是在指定的数据中寻找某一特定的数据。 查找结果有两种,即找到(查找成功)和未找到(查找失败)。 2.顺序查找 (1)顺序查找的基本思想 从第一个数据开始,从左往右(或从上到下)将数据按顺序逐个与给定的值进行比较,若某个数据和给定值相等,则查找成功,找到并输出所查数据的位置;反之,查找失败。 若有n个数,则可能的最多查找次数为n。 (2)顺序查找算法基本框架 设要查找的数为key,待查找的数存放在数组d中。 For语句框架: For i=1 to n 若d(i)=key,则表示找到,做相应处理 Next i 若i>n表示未找到 Do While语句框架: i=1 Do while i<=n 若d(i)=key,则表示找到,做相应处理 i=i+1 Loop 若i>n表示未找到 (3)顺序查找的程序实现 在n个数组元素中依次查找,找到第1个满足条件的值,找到即结束,输出找到元素所在的位置;若找不到,输出“未找到”。 程序实现: 设要查找的数据是key(在文本框Text1中输入),查找的数据存放在数组d中。pos为找到数的位置,pos=0表示未找到。 P表示查找的次数。 key=Val(Text1.Text)′Val要根据实际情况决定是否要添加 p=0 pos=0 find=False′find表示查找结果 i=1 Do While i<=n And Not find′表示还没找完并且还未找到,则继续查找,Not find也可表示为find=false p=p+1 If key=d(i) Then pos=i find=True End If i=i+1 Loop If find Then′也可表示为If find=true then Text2.Text=“在d(”+Str(pos)+“)中” Else Text2.Text=“未找到” End If 3.对分查找 (1)对分查找的基本思想 在有序的数据序列中(一般存放在数组中),首先把要查找的数据与数组中间位置的元素进行比较,如果相等,则查找成功并退出查找;否则,根据数组元素的有序性,确定数据应在数组的前半部分还是在后半部分查找;在确定了新的查找范围后,重复进行以上比较,直到找到或未找到为止。 温馨提示:①对分查找的前提是被查找的数据序列必须是有序。②“未找到”是指当指定范围内的起点大于终点仍未找到该数据。 (2)对分查找算法基本框架 说明:要查找的数为key,待查找的数存放在数组d中。 i为查找范围的起点,j为查找范围的终点,m为范围[i,j]的中间位置。 i=1 j=n Do While i<=j 计算中点位置m 比较key与d(m),并做相应处理 Loop 若i>j,则表示未找到 (3)对分查找程序实现 在n个数组元素中依次查找,找到第1个满足条件的值,找到就结束,输出找到元素所在的位置;若找不到,输出“未找到”。 程序实现: 设要查找的数据是key(在文本框Text1中输入),查找的数据存放在数组d中。在文本框Text2中输出查找结果,若找到输出“找到!位置为:X”,否则输出“未找到!” 在文本框Text3中输出共查找的次数。 p表示查找的次数。 核心代码为(以升序为例): key=Val(Text1.Text)′表示要查找的数 p=0′表示查找的次数 find=False′查找的结果,若find=true表示找到,find=false表示未找到 i=1′查找的起始范围 j=n′查找的终点范围 Do While i<=j And Not find′如果还未找完并且未找到 p=p+1′查找次数计数 m=(i+j)\2′计算中点位置m If key=d(m) Then′表示找到的情况 find=True Text2.Text=“找到!位置为:“+Str(m) End If If Key>d(m)Then′表示查找的数比中间位置上的数大时 i=m+1 Else′表示查找的数比中间位置上的数小时 j=m-1 End If Loop If Not find Then Text2.Text=“未找到!” Text3.Text=“共查找的次数为:”+Str(p) 温馨提示:计算中点位置的语句还可以写成:m=Int((i+j)/2)或m=Fix((i+j)/2)。 三、递归算法 1.递归的概念 函数或过程调用其本身,称为递归。 2.递归算法的基本思想 递归算法的基本思想是把规模较大的、较难解决的问题变成规模较小的、容易解决的同一问题,规模较小的问题又变成规模更小的问题,直到可以直接得出它的解,从而得到原来问题的解。 3.采用递归算法须具备的条件 (1)每一步骤解决问题的方法要一致。 (2)要有结束的边界条件。 四、Connection对象 用Connection建立和数据库的连接时,首先创建一组ADO对象用于设置打开连接和产生结果集,需要设置连接字符串ConnectionString的参数。下列语句定义一个Connection对象的实例conn,conn是实例的名称,命名规则与VB变量定义相同,并设置conn的连接字符串: Dim conn As New ADODB.Connection Dim abc As New ADODB.Recordset conn.ConnectionString=“Provider=Microsoft.ACE.OLEDB.12.0;Data Source =”& App.Path & “\souse1.accdb” 其中,“Provider”用于指定连接的提供者,“Data Source”用于指定数据库的文件名(含绝对路径)。App.Path返回当前应用程序所在的绝对路径。 Connection对象具有Open、Execute、Close等方法,其中Open方法用于建立到数据源的连接,Execute用于执行指定的查询、SQL语句或特定提供者的文本等内容,而Close方法则用于关闭连接。 五、Recordset对象 用Recordset对象从数据库中查询记录时,要设置ActiveConnection属性的值。语句Set abc.ActiveConnection=conn,使Recordset对象的实例abc与Connection对象的实例conn建立关联。 在abc与conn建立关联后,可用Recordset对象的Open方法打开、查询数据表的记录。 Open方法的参数为SQL命令。如:abc.Open“SELECT*FROM info”运行后,记录集abc中的数据为SQL语句“SELECT*FROM info”查询到的记录。 同样,Recordset对象的Close方法用于关闭对象。 Abc.close表示关闭记录集。 Recordset对象的Fields集合用于返回当前记录中的数据,如:abc.Fields(“book”)返回当前记录中”book”字段的值;abc.Fields(0)返回当前记录中第一个字段的值,如果第一个字段名为“book”,则abc.Fields(0)与abc.Fields(“book”)返回值相同。例如Recordset对象实例abc打开了下表的记录集: Recordset对象打开的记录集: 假设当前记录为第2条记录,则Fields集合返回当前记录某个字段的数据有以下两种方法: (1)abc.Fields(字段序号),其中字段序号从0开始编号。 (2)abc.Fields(“字段名称”) 故abc.Fields(0)和abc.Fields(“book”)都返回“红楼梦”,abc.Fields(1)和abc.Fields(“author”)都返回“曹雪芹”,abc.Fields(2)和abc.Fields(“price”)都返回“53.6”,abc.Fields(3)和abc.Fields(“Publishing”)都返回“上海教育出版社”。 通过Recordset对象从数据库中返回的这些数据可以通过数组的形式存储,以方便我们后序进行统计、排序、查找等处理。 Recordset对象的AddNew方法为可更新的Recordset对象创建一个新记录,它添加一条新的空记录,并且定位在该记录上;Delete方法可将当前记录从记录集中删除;Edit方法可以编辑修改数据库的记录,注意首先要将需要编辑的记录成为当前记录,然后使用Edit方法修改记录内容,使用Edit方法后,再移动记录或者使用Update方法把数据存入到数据库中;Move方法可以使不同的记录成为当前记录,主要有5种使用方法: MoveFirst:移动到记录集的第一条记录。 MoveLast:移动到记录集的最后一条记录。 MoveNext:移动到记录集的下一条记录。 MovePrevious:移动到记录集的上一条记录。 Move:可以使用Move方法向前或向后移动若干条记录。 但应注意:若到数据表结尾处还继续向下移动,程序会出错,因此在使用MoveNext 时要判断Recordset的BOF和EOF属性,判断记录指针是不是到达首记录之前或尾记录之后。EOF取值为“True”时表示已经到达记录集的结尾,否则EOF的值为“False”。 若BOF和EOF的取值均为“True”则表示此记录集为空。 六、SQL:Select语句 SELECT语句是结构化查询语言SQL中常见的语句,主要用于从数据表中查询数据,如语句“SELECT*FROM info”表示查询数据表“info”的全部数据。 语句总结如下: (1)定义Connection对象的实例conn和Recordset对象的实例abc。 Dim conn As New ADODB.Connection Dim abc As New ADODB.Recordset (2)为实例conn设置ConnectionString属性值。 conn.ConnectionString=“Provider=Microsoft.ACE.OLEDB.12.0;DATA Source =”& App.Path& ”\souse1.accdb” (3)打开与数据库的连接。 conn.Open (4)建立实例abc与conn之间的关联。 Set abc.ActiveConnection=conn (5)执行SELECT命令,将查询结果返回给abc。 abc.Open“SELECT*FROM info” (6)在应用程序中引用abc中当前记录的字段值。 Label1.Caption=abc.Fields(“book”) Label2.Caption=abc.Fields(“price”) (7)关闭记录集。 Abc.close (8)关闭与数据库的连接。 conn.Close 【例1】(2016·4月浙江高考)有如下程序段: For i=1 To 2 For j=5 To i+1 Step-1 If a(j)>a(i) Then t=a(j):a(j)=a(i):a(i)=t End If Next j Next i 数组元素a(1)到a(5)的值依次为“33,24,45,16,77”,经过该程序段“加工”后,数组元素a(1)到a(5)的值依次为() A.77,45,33,16,24 B.77,33,45,16,24 C.77,24,45,16,33 D.77,45,33,24,16 解析分析本题程序段,外层循环到2,说明只进行了两遍排序。第1遍排序a(5)到a(2)依次与a(1)比较,较大数与a(1)交换,结果为:77,24,45,16,33;第2遍排序a(5)到a(3)依次与a(2)比较,较大数与a(2)交换,结果为:77,45,33,16,24。 根据程序的代码特征,没有中间变量存放较大数,数据的交换在内层循环中,形式上很像冒泡排序,但仔细分析,排序时关键的数据比较是“a(j)>a(i)”,不是相邻两个数依次比较,第i遍排序时后面的数都依次和a(i)比较,通过交换使a(i)最大。所以本程序段算法不是简单冒泡排序,也不是简单选择排序,类似选择排序的变形。 答案 A [变式1]篮球联赛中,有5个班级的比赛积分依次为14,11,13,8,9。若采用冒泡排序算法对其进行从小到大排序,则完成第二遍时的结果是() A.8,11,13,14,9 B.8,9,13,14,11 C.8,9,14,11,13 D.14,13,11,9,8 解析从小到大冒泡排序的基本思想是从最后的一个元素起,自后向前比较相邻的两个数据,将较小的数据换到前面,较大的换到后面。重复这一过程,直到处理完最后两个数据,称为一遍加工。因此第一遍加工时,9和8,9不动;8和13,13换到后面,8换到前面;8和11,11换到后面,8换到前面;8和14,14换到 后面,8换到前面。这是第一遍加工,结果是:8,14,11,13,9。第二遍加工时,9和13,13换到后面,9换到前面;9和11,1l换到后面,9换到前面;9和14,14换到后面,9换到前面。这是第二遍加工,结果是:8,9,14,11,13。答案 C [变式2]有如下VB程序段: For i=1 to 3 For j=5 to i step-1 If a(j) K=a(j):a(j)=a(j+1):a(j+1)=k End if Next j List1.Additem str (a(i)) Next i 数组元素a(1)到a(6)的数据依次为“1,5,7,6,9,3”,经过该程序段加工后,列表框List1中显示() A.9、7、6 B.1,3,5 C.9、7、6、1、5、3 D.9,7,6,5,3,1 解析i表示排序的趟数,只排了3趟,且只显示了前面3个数。j表示比较的位置,从后向前比较,条件a(j) [变式3]有如下程序段: tot=0 For i=1 To 4 yes=False For j=5 To i+1 Step -1 If a(j)>a(i) Then yes=True:tot=tot+1 t=a(j):a(j)=a(i):a(i)=t End If Next j If yes=False Then Exit For Next i 数组元素a(1)到a(5)的值依次为“33,24,4,16,77”,经该程序段“加工”后,tot的值为() A.2 B.3 C.4 D.5 解析J表示比较的位置,从后向前比较,条件a(j) 答案 B [变式4]VB程序段如下: exchange=0 last_change=8 Do While last_change>1 current=1 For j=1 To last_change-1 If a(j) exchange=exchange+1 tmp=a(j) a(j)=a(j+1) a(j+1)=tmp current=j End If Next j last_change=current Loop 数组元素a(1)到a(8)的值依次为“15,13,20,14,12,9,5,1”,执行该程序段,exchange的值为() A.2 B.3 C.4 D.5 解析J表示比较的位置,从前向后比较,条件a(j) 答案 B 【例2】(2017·11浙江选考)小李基于冒泡排序算法编写一个VB程序,功能如下:在文本框Text1中显示排序前的数据,单击“排序”按钮Command1,在文本框Text2中显示剔除重复数据后的升序排序结果。程序运行界面如下图所示。 实现上述功能的VB代码如下,但加框处代码有错,请改正。 Const n=10 Dim a(1 To n)As Integer Private Sub Command1_Click() Dim i As Integer,j As Integer,t As Integer Dim bottom As Integer′剔除重复数据后元素的个数 ′获取排序前数据依次存储在数组a中,并在文本框Text1中显示。代码略bottom=n i=1 Do While i<=bottom-1 For j=bottom To i+1 Step-1 If a(j) t=a(j):a(j)=a(j-1):a(j-1)=t ElseIf a(j)=a(j-1) Then′若相邻数据相等,进行剔除处理 a(bottom)=a(j)′(2) bottom=bottom-1 End If Next j i=i+1 Loop Text2.Text=“” For i=1 To bottom Text2.Text=Text2.Text+Str(a(i)) Next i End Sub 其中,方框(1)处应改正为________; 方框(2)处应改正为________。 答案(1)a(j)a(j)或其他等价表达式 (2)a(j)=a(bottom)或其他等价语句 [变式5](2016·10月浙江选考)小吴为了探究冒泡排序过程中数据的“移动”情况,编写了一个VB程序,功能如下:在列表框List1中显示排序前数据(存储在数组a中),在文本框Text1中输入初始位置(即下标值),单击“排序”按钮Command1后,在标签Label1中显示指定初始位置的数据在排序过程中的位置变化情况,排序后的数据显示在列表框List2中。程序运行界面如图所示。 实现上述功能的VB程序如下,但加框处代码有错,请改正。 Dim a(1 To 8)As Integer Dim n As Integer Private Sub Form_Load() ′n=8,排序前的8个数据存储在数组a中,并在列表框List1中显示 ′代码略 End Sub Private Sub Command1_Click() Dim i As Integer,j As Integer,k As Integer Dim pos As Integer′变量pos存储指定数据的位置(即下标值) Dim s As String′变量s存储pos变化情况 s=Text1.Text pos=Val(Text1.text) For i=1 To n-1 For j=n To i+1 Step -1 If a(j)<a(j-1) Then k=a(j)′(1) a(j-1)=a(j) a(j)=k ′如果pos位置的数据参与交换,则更新pos值,记录pos变化情况 If pos=j Then pos=j-1 s=s+“→”+Str(pos) Else′(2) pos=j s=s+“→”+Str(pos) End If End If Next j Next i Label1.Caption=“位置变化情况:”+s For i=1 To n List2.Addltem Str(a(i)) Next i End Sub 其中,加框(1)处应改正为________; 加框(2)处应改正为________。 解析仔细阅读题干说明和程序及程序注释,先从整体判断各程序段功能及各变量的作用,再具体分析出错位置的程序行进行改错。 (1)此位置程序段为冒泡排序相邻两个数据进行比较后,逆序的两数交换数据,即交换两个变量的值,分析后面两程序行,判断(1)方框处应该是“k=a(j-1)”。 (2)阅读程序注释,(2)框处所在分支语句功能为“如果pos位置的数据参与交换,则更新pos值,记录pos变化情况”,这个是在外层的判断语句的基础之上进行的,即两个相邻数a(j) 答案(1)k=a(j-1)(2)ElseIf pos=j-1 Then [变式6]n个数据的冒泡升序排序需要经过n-1遍的加工,每一遍加工自下而上比较相邻两个数据,把较小者交换到上面,在第i遍加工过程中需要进行n-i 对数据的比较。在某些情况下,第i遍加工过程中,在上面部分较小数据已经有序情况下,不需要再进行n-i对数据的比较。如对“17,18,19,24,23,20”这6个数据排序中,第1遍排序结束后数据为“17,18,19,20,24,23”,第2遍排序时不再需要对20及其前面4个数据进行比较。以下程序实现了冒泡排序的优化,但加框处代码有误,请改正。 Dim n As Integer Dim a(1 To 100)As Integer Private Sub Form_Load() ′n=10,排序前生成的数据存储在数组a中,并在列表框List1中显示′代码略 End Sub Private Sub Command1_Click() Dim i As Integer,j As Integer,start As Integer,t As Integer i=0′(1) Do While i start=n For j=n To i Step-1 If a(j) t=a(j):a(j)=a(j-1):a(j-1)=t start=j End If Next j start=i′(2) Loop For i=1 To n List2.AddItem Str(a(i)) Next i End Sub 其中,加框(1)处应改正为________; 加框(2)处应改正为________。