按照姓名升序排序的代码_关于索引排序的两道经典例题

说在前面

    索引排序是近年来各类模拟考试中的新宠,很多老师都花了很多力气给学生做各种练习,希望学生能够掌握相关算法,但是由于排序算法本身就变例颇多,再引入索引数组,理解难度进一步增大,让很多学生不知所措。

事实上我们可以把“索引”理解成“数组下标”的别称,就好比超市中存储柜的编号,通过这个编号就能找到相应的存储空间。

“索引排序”是和“物理排序”相对应的概念,所谓物理排序就是改变记录(数组元素)存放的物理位置,即直接对数组进行排序;而索引排序通过增加一个索引数组来存储各数组元素的下标,在排序时不需要对原数组进行排序,只需对索引数组排序即可。这样可以大大提高排序的效率,也可以避免因修改原数组的内容而造成的数据混乱。

在本文中,笔者打算使用2个经典的案例,由浅入深地介绍引入索引数组的原因,和利用索引数组将原始数组进行有序输出的原理,进而搞清楚索引排序的本质特征。由于笔者水平有限,表述难免存在不严谨之处,还请各位老师批评指教。

25e58b46a74bf64ad4721764eb82ea86.png

例1. 如下图所示,List1显示了排序前学生的姓名和成绩,点击按钮1或按钮2都能按照成绩从高到低将学生的姓名和成绩显示到List2中。按钮1和按钮2分别采用了不同的方法来实现排序功能,其中Command1_Click()使用选择排序算法对数组score和pname都进行了排序,再输出排序后的姓名和成绩;但是Command2_Click()并没有对数组score和pname进行排序,而是引入了一个辅助数组q,数组q按顺序存储了各学生的序号,q(i)=k表示排名第i的人其序号为k。我们根据学生成绩对数组q进行排序,并按顺序输出学生姓名和成绩。

55df780034ad20717fdf3d4b1af448de.png

下面的代码实现了上述功能,请将缺失的代码补充完整:

Const n = 6

Dim score(1 Ton) As Integer '存储学生的成绩

Dim pname(1 Ton) As String  '存储学生的姓名

Dim i AsInteger, j As Integer, k As Integer

Private SubForm_Load()

    ‘将学生成绩和姓名分别存储到数组score和pname,并显示在列表框List1中,代码略

End Sub

Private SubCommand1_Click()

    Dim tscore As Integer, tname As String

    For i = 1 To n - 1

        k = i

        For j = i + 1 To n

            If ①                      Then k = j

        Next j

        If k <> i Then

            tscore = score(i): score(i) =score(k): score(k) = tscore

            tname = pname(i): pname(i) = pname(k):pname(k) = tname

        End If

    Next i

    For i = 1 To n

        List2.AddItem pname(i) + Str(score(i))

    Next

End Sub

Private SubCommand2_Click()

    Dim q(1 To n) As Integer, tpos As Integer

    For i = 1 To n

        q(i) = I  '初始化排名为i的人序号也是i

    Next

    For i = 1 To n - 1

        k = i

        For j = i + 1 To n

            If ②                    Then k = j

        Next j

        If k <> i Then

            tpos = q(i): q(i) = q(k): q(k) =tpos

        End If

    Next i

    For i = 1 To n  '按照排名输出学生的姓名和分数

        List2.AddItem ③                      

    Next

End Sub

例1.【答案】

① score(j) > score(k) 

② score(q(j)) > score(q(k)) 

③ pname(q(i)) + Str(score(q(i)))

【解析】

“索引排序”是和“物理排序”相对应的概念,所谓物理排序就是改变记录(数组元素)存放的物理位置,即直接对数组进行排序;而索引排序通过增加一个索引数组来存储各数组元素的下标,在排序时不需要对原数组进行排序,只需对索引数组排序即可。

Command1_Click()以成绩为关键字,使用选择排序算法对数组score和pname都进行了排序,每趟排序过程中,将score数组中最大值的下标存储在变量k中,故第①空答案为score(j)> score(k);Command2_Click()并没有对数组score和pname进行排序,而是根据学生成绩对索引数组q进行排序,每趟排序过程中,将score数组中最大值的下标存储在q(k)中,故第②空答案为score(q(j))> score(q(k))。

最后要按顺序输出学生姓名和成绩,因为Command2_Click()并没有对数组score和pname进行排序,故不能直接输出pname(i)和Str(score(i)),而是要输出pname(q(i))和Str(score(q(i)))。

例2. 阿福编写VB程序演示索引排序算法,功能如下:先单击“生成”按钮Command1,在数组a中生成n个两位整数,并显示在标签Label1中;再单击“排序”按钮Command2,则对索引数组b排序,将数组a中的元素按升序存储到数组c中,分别将排序后的索引数组b和有序数组c显示在标签Label2和Label3中,并清空原始数组a;最后单击“还原”按钮Command3,将排序前的原始数据存储到数组d,并显示在标签Label4中。运行界面如图所示,请回答下列问题:

1b217638a8fec325d3f3f994204ca52e.png

(1)当n=6时,若数组元素a(1)到a(6)的值依次为30,50,60,10,20,40,则单击“排序”按钮后,数组元素b(1)到b(6)的值依次为                                     。

(2)实现上述功能的VB程序如下,请将缺失的代码补充完整。

(3)程序加框处代码有错,请改正。

Const n = 6

Dim a(1 To n) As Integer, b(1 To n) AsInteger

Dim c(1 To n) As Integer, d(1 To n) AsInteger

Private Sub Command1_Click()

   Dim i As Integer

   For i = 1 To n

       a(i) = Int(Rnd * 90) + 10

       b(i) = i

       Label1.Caption = Label1.Caption + Str(a(i))

   Next i

End Sub

Private Sub Command2_Click()

   Dim i As Integer, j As Integer, k As Integer, t As Integer

   For i = 1 To n - 1

       For j = n To i + 1 Step -1

           If ①                      Then

                t = b(j): b(j) = b(j - 1): b(j- 1) = t

           End If

       Next j

   Next i

   For i = 1 To n

       c(i) = ②                     

       Label2.Caption = Label2.Caption + Str(b(i))

       Label3.Caption = Label3.Caption + Str(c(i))

   Next i

   For i = 1 To n

       a(i) = 0

   Next i

End Sub

Private Sub Command3_Click()

   Dim i As Integer

    For i = 1 To n

       d(i) = c(b(i))

   Next i

   For i = 1 To n

       Label4.Caption = Label4.Caption + Str(d(i))

   Next i

End Sub

例2.【答案】

(1)4,5,1,6,2,3

(2)① a(b(j)) < a(b(j - 1)) 

    ② a(b(i))

(3)d(b(i)) = c(i)

【解析】

索引排序最本质的特征是把原始数组a的元素下标存储到索引数组b中,因此无论用哪种算法对数组b排序,在排序过程中,都要用b(i)来表示原始数组中第i个元素的下标。

当n=6,数组元素a(1)到a(6)的值依次为30,50,60,10,20,40时,我们把原数组a、索引数组b、有序数组c和还原数组d各个元素的值依次显示如下表所示:

cbb248cb6e1dd3f6f27324b10dbd7cac.png

         程序使用冒泡排序算法对索引数组b排序,将数组a中的元素按升序存储到数组c中,因为已经将数组a的元素下标存储到了索引数组b中,所以两个相邻元素的下标不再是j和j-1,而是b(j)和b(j - 1),故第①空答案为a(b(j))< a(b(j - 1));排序后数组b存储的是对a中元素按升序排列的下标,若b(i)=k,则表示第i个元素(即排名为i)的下标为k,因此可以找到数组a、b、c之间的关系:c(i) = a(b(i)),从而得到对应数组c的值。

         根据数组a、b、c之间的关系:c(i) =a(b(i)),我们既可以由a和b求出c,也可以由b和c求出a,即a(b(i)) = c(i),把数组a改成d,即得到第3题答案d(b(i)) = c(i)。

拓展思考:

         在例题1和例题2中,我们分别用选择排序和冒泡排序算法对索引数组进行了排序,其实索引排序的本质并不在于用哪种算法来排序,而是要理解索引数组b中存储的是原始数组的元素下标,因此无论用哪种算法对数组b排序,在排序过程中,都要用b(i)来表示原始数组中第i个元素的下标。

         为了帮助大家进一步理解索引排序,我给出了两段分别用插入排序和计数排序实现例题1功能的代码,请认真阅读代码,并将缺失的代码补充完整:

Private Sub Command3_Click() '插入排序

Dim q(1 To n) AsInteger, tpos As Integer

For i = 1 To n

q(i) = i  '初始化排名为i的人序号也是i

Next

For i = 2 To n

       tpos = ①         

       For j = i - 1 To 1 Step -1

           If score(q(j)) <= score(tpos) Then Exit For

           ②                      

       Next j

       q(j + 1) = tpos

   Next i

For i = 1 To n  '按照排名输出学生的姓名和分数

List2.AddItem ③                      

Next

End Sub

Private Sub Command4_Click() '计数排序

   Dim q(1 To n) As Integer, tpos As Integer

   Dim tong(0 To 100) As Single

   For i = 0 To 100       '把桶清空

       tong(i) = 0

   Next i

   For i = 1 To n          '将数据装入桶中

      tong(score(i)) = ④                

   Next i

   For i = 1 To 100 '从第2个桶开始依次求出每个桶的前缀和

       tong(i) = tong(i) + tong(i - 1)

   Next i

   For i = n To 1 Step -1  '反向填充目标数组(索引数组)

      q(⑤                ) = i

      tong(score(i)) = tong(score(i)) - 1

   Next i

   For i = 1 To n  '按照排名输出学生的姓名和分数

       List2.AddItem ⑥                      

   Next

End Sub

【答案】

① q(i) 

② q(j + 1) = q(j) 

③ pname(q(i)) + Str(score(q(i)))

④ tong(score(i)) + 1 

⑤ tong(score(i)) 

⑥ pname(q(i)) + Str(score(q(i)))

为了保证解析的原创性和思维的独特性,我都是独立解题后,先不看答案(除非题目不会做),直接把解析写好,再去看答案。

当然,如果发现参考答案有更好的思路,我还是很乐于学习和借鉴的。同时,由于本人水平有限,解析中难免出现疏漏甚至错误之处,敬请谅解。

无论是赞同还是反对我的看法,都请你给我留言。如果你有新的想法,千万不要憋在心里,请发出来大家一起讨论。让我们相互学习,共同进步!

需要本文word版的,可以加入“选考VB算法解析”知识星球参与讨论和下载文件,“选考VB算法解析”知识星球汇集了数量众多的同好,更多有趣的话题在这里讨论,更多有用的资料在这里分享。

我们专注选考VB算法,感兴趣就一起来!

a39c1f3f1237476cdb1109da011e9688.png

相关优秀文章:

阅读代码和写更好的代码

最有效的学习方式

金丽衢十二校2019学年高三第二次联考技术卷第15题解析

2020年4月绍兴市适应性试卷第16题解析

桶排序和索引排序算法课后练习

选考VB算法专题系列讲座10桶排序和索引排序算法

桶排序和索引排序算法导学案

计数排序再思考——从2020年1月第16题谈起

54d4163a87ccd17d0d69c42a94850340.png

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值