美文网首页
VB程序设计

VB程序设计

作者: 莫底凯 | 来源:发表于2018-01-13 15:22 被阅读0次

    VB程序设计

    VB6.0似乎已经成为开发者的往事,但是Microsoft Office系列软件的控制和操作仍然是基于VB6.0的。本项目是为所有学习VB6.0的同学而建立的。

    问题1: 排序算法

    排序算法是计算机程序设计中最经典的算法,在计算机的专业课《数据结构》中有大量的讨论和分析。我们在这里只讨论最简单的选择排序冒泡排序。讨论从一个填空题开始。

    ' 功能:将数组a()中的元素按从小到大排序'
    ' 参数:数组a()的下标索引为从1到30'
    Sub bubble_sort(a() As Integer)
        For i = 1 To 29
            For j = 【2】
                If a(i) > a(j) Then
                    m = a(i): a(i) = a(j): a(j) = m
                End If
            Next j
        Next i
    End Sub
    

    问题:【2】这个地方应该填什么?是 i+1 To 30?还是 1 To 30-i?

    • 首先,最正确的姿势是记住!甭管是冒泡还是选择排序,这里j的取值应该与i正好错开1,【2】处应该填:i+1 To 30
    • 其次,理解排序的原理。为什么不是:1 To 30-i呢?
      首先,我们要明确目标。因为要对数组a()从小到大排序,我们期望:依次扫描a()中的每个元素,每扫描到一个元素a(i),都使得它是剩下的元素(从a(i)到a(30))中最小的。怎么做到呢?可以从a(i)一直扫描到a(30),找到最小的元素a(p),令a(i)和a(p)的值交换(注意:这里不能直接让a(i)=a(p),否则,a(i)的原有值就不见了)。用下面的伪代码表示:
    '代码块1
    Sub selection_sort(a() As Integer)
        For i = 1 To 30
            '从a(i) 到 a(30)中找到最小的元素a(p)'
            '将a(i)和a(p)的值交换'
        Next i
    End Sub
    

    那么,怎么从a(i) 到 a(30)中找到最小的元素a(p)呢?可以这样做:

    '代码块2
    p = a(i) '首先,假设a(i)就是最小的'
    For j = i To 30 '从a(i) 扫描到 a(30)'
        If p > a(j) Then '一旦发现p比a(j)还大,就让p指向a(j)'
            p = a(j)
        End If
    Next j
    

    上述做法,就是选择排序的思想。我们可以将代码优化下:
    首先,j 不必从 i 开始扫描,因为当 j = i 时,a(j)没有必要跟a(p)进行比较(这时,p 也等于 i)。
    其次,p 指向a(i)的索引就可以了,没有必要指向a(i)。

    '代码块3
    p = i ' 假设a(i)就是最小的
    For j = i+1 To 30
        If a(p) > a(j) Then  '一旦发现a(p)比a(j)还大,就让 p 指向 j
            p = j
        End If
    Next j
    

    这时,将代码块3嵌入代码块1,就可以得到完整的选择排序的代码了:

    '代码块4
    Sub selection_sort(a() As Integer)
        For i = 1 To 30
            '从a(i) 到 a(30)中找到最小的元素a(p)
            p = i '假设a(i)就是最小的
            For j = i+1 To 30
                If a(p) > a(j) Then '一旦发现a(p)比a(j)还大,就让 p 指向 j
                    p = j
                End If
            Next j
            '将a(i)和a(p)的值交换(代码略)'
        Next i
    End Sub
    
    • 经过上面的推演,我们就得到了一个双重循环。反过来,如果直接拿到的就是这样一个双重循环的话,会不会感觉阅读起来很困难?实际上,只要把外层循环 i 固定为某个特定的值来理解内层循环 j 就可以了。
    • 再来看冒泡排序法。它与选择排序法最大的不同在于:在其内层循环 j 中,一旦发现a(p)比a(j)还大,就让 a(p) 和 a(j) 的值交换,而 p 是始终指向 i 的(因为a(p)中一直存放最小的值,所以,p就没有必要再移动了)。这样,每经过一次内层循环,就相当于剩下元素中具有最小值的那个元素(具有最小的质量)从水底下浮出来了,因此称为“冒泡排序法”。具体代码如下:
    ' 代码块5
    Sub selection_sort(a() As Integer)
        For i = 1 To 30
            ' 从a(i) 到 a(30)中找到最小的元素a(p)
            ' 假设a(i)就是最小的,并且始终存放剩余元素中的最小值
            For j = i+1 To 30
                If a(i) > a(j) Then '一旦发现a(i)比a(j)还大,就让它们交换
                    m = a(i): a(i) = a(j) : a(j) = m
                End If
            Next j
        Next i
    End Sub
    
    • 那么,上面的“选择排序”和“冒泡排序”哪个更优呢?也就是,哪个排序算法的速度更快呢?显然是选择排序。因为冒泡排序在最坏的情况下需要 30-(i+1)+1=30-i 次 a(j) 和 a(i) 的交换,而选择排序只要交换交换 1 次即可。
    • 再来看同学的问题,同学尝试将内层循环 j 设置为 1 To 30-i 有什么问题呢?事实上,这样做就意味着:该做的没有做,不该做的却费力去做。第一,该做的没有做。你看,这样做只能找到从a(1)到a(30-i)中的最小值,那a(30-i)之后的元素呢?第二,不该做的却费力去做。为了让 a(i) 为剩下元素中的最小值,还需要做许多冗余的工作:它还要跟它之前的已经比它还小的元素依次比较,这完全是没有必要的,因为比它大的元素,只可能在它后边。
    • 练习。如果我们非要将内层循环 j 设置为 1 To 30-i 呢?如果非要这样做,外层循环 i 的设置必须改变,它必须从 a(i) 的最后一个元素倒着走向 a(i) 的第一个元素,以保证:每次a(i)中都存放最大值。这样的程序该如何写?请同学们自行练习。

    相关文章

      网友评论

          本文标题:VB程序设计

          本文链接:https://www.haomeiwen.com/subject/eymcoxtx.html