语言、界面、源程序
(1)语言
程序中通过Virual BASIC6.0语言来实现。
(2)界面
界面非常简单,建立一标准EXE工程,其caption设为“猴子分食桃子”,一切OK。我们将代码加给Form_Click()即窗体的单击事件,将来运行时,我们只要用鼠标单击一下窗体,程序就执行了。
(3)源程序
Option Explicit
Private Sub Form_Click()
Dim x, s, k, i As Integer '声明变量
x = 6
k = 0 '整除标志
While k4
s = x '第5只猴子时总数
k = 0
For i = 4 To 1 Step -1 '第4-1只时的数量
s = s * 5 / 4 + 1
If Int(s) = s Then '符合情况则将整除标志加1
k = k + 1
End If
Next i
x = x + 5 '第次增5
Wend
Print s '输出
End Sub
(上程序在VB60 Win2000下调试通过)
小结
上面应用的推导方法就是倒推法。生活中的更多问题采用顺推法就可得到,也即从1-N,但不论倒推还是顺推,能递推出并解出问题是我们的本意。
语言、界面、源程序
(1)语言
程序中通过Virual BASIC6.0语言来实现。
(2)界面
界面非常简单,建立一标准EXE工程,其caption设为“删数问题”。放入三个文本框和两个按钮,文本框起到输入两个数和输出结果的作用,按钮用来控制执行,再放入三个标签起到说明的作用。
(3)源程序
Private Sub CmdDelnum_Click()'开始删数按钮
Dim i As Integer
Dim j As Integer
Dim n As String '原数
Dim s As Integer '删数的个数
Dim nlength As Integer 'N的长度
Dim a() As Integer '放位数数组
Dim k As Integer '记录最大值位置
TxtOutput.Text = ""
n = TxtNum.Text
s = Val(TxtS.Text)
nlength = Len(n)
ReDim a(nlength - 1)
'将各位的值放入数组
For i = 0 To nlength - 1
a(i) = Mid(n, i + 1, 1)
Next i
'执行贪心算法s步
For j = 1 To s
k = 0
For i = 1 To nlength - j
If a(k) = 10 Then
monkey = 1
Else
monkey = 2 * (monkey(x + 1) + 1)
End If
End Function
我们定义monkey()函数的时候通过monkey()自身来进行了定义,这就是递归。递归是个特殊的循环,是一个有着非常美妙的循环规则的循环。上题中我们只要将monkey(1),即第一天打印出来,一切OK。而这中间究竟是怎么工作的,我们可以不管。
正是有了monkey()函数,在对其自身调用的过程中实现了我们的所求,关于函数、子程序和他们之间发生的故事还有很多,仅仅列举了其中奇妙的几点,还有许多东东等着您的发现和利用。
小结
函数和子程序是程序瘦身计划的一部分,通过它们可以使程序中的代码适当减肥,长度维持在一个更合理的位置。这种作用和循环的瘦身作用一起,使一个执行很长的代码可以变得很简洁。这也更适合我们利用计算机作为工具的目的:人类做尽量少的工作,计算机仍能解决原先的问题。
另一个奇妙之处是:他们创造了递归!
各个击破——分治法破解难题
问:“问题不能一下子解决,难道不能分开解决吗,有没有算法能实现各个击破以求解决问题呢?”
答:“可以的,通过各个击破的方法解决问题的算法叫做分治法。下面我们通过示例来看一下。”
什么是分治法
为了解决一个问题,算法有时需不止一次地对自身进行调用,来解决相类似的子问题。这样的算法通常称为分治法:将原问题分成n个规模较小而结构与原问题相似的子问题。下面通过排序的一种方法来看一下。
希尔排序即是采用分治法来进行排序的,又称做缩小增量排序,其思想是:把已经在数组中的数据按下标的一定增量分组,对分出的每一小组使用插入排序,随着增量逐渐减小,所分成的组包含的数据越来越多,直到减小到1时,整个数据合并成一组,构成一组有序数,则完成排序。
示例:十个数,从大到小排序。
数据放在一个数组a(10)中,假如原始数据如下:70. 53. 57. 28. 30. 77. 1. 76. 81. 70,则排序过程如下:
增量值
5:77. 53. 76. 81. 70. 70. 1. 57. 28. 30.
2:77. 81. 76. 70. 70. 57. 28. 53. 1. 30.
1:81. 77. 76. 70. 70. 57. 53. 30. 28. 1.
其中上面三个增量值对应的都是以该增量完成本轮排序后的情况,看增量为5时要和原始数据比较,增量为2的情况要和5比较,1要和2比较,这样其中的规律就清楚了。
子程序如下
要用实现希尔排序,关键是把握好增量的变化情况和最终结束的控制,设置变量gap为增量,其值取要排序的所有数据的个数的二分之一(本例中为5),比较时先将第1个数同第6个比,较大的放到前面,较小的放到后面,2同7,直至全部比较完成;下一次用现在的gap的二分之一作为增量,再进行增量大小转换;…;当其为0时结束。原无序序列排成了有序序列了。从上面分析中不难看出,通过和gap增量有关的两重嵌套循环就能将排序功能实现。详细源程序如下:
Sub shellsort(ByVal n As Integer) '希尔排序子程序
Dim i, j, gap As Integer
Dim k,xAs Integer
gap = Int(n / 2) '置初值
While gap > 0
For i = gap + 1 To n
j = i - gap
While j > 0
If a(j) < a(j + gap) Then
x = a(j)
a(j) = a(j + gap)
a(j + gap) = x
j = j - gap
Else
j = 0
End If
Wend
Next i
gap = Int(gap / 2)’减小增量
‘输出结果
TxtList.Text = TxtList.Text + Str(gap) + ":"
For k = 1 To n
TxtList.Text = TxtList.Text + Str(a(k)) + "."
Next k
TxtList.Text = TxtList.Text + vbCr + vbLf
Wend
End Sub
其他源程序
希尔排序按钮对应的源程序如下:
Private Sub CmdShell_Click() '希尔排序
Dim i As Integer
TxtList.Text = ""
Txtorigin.Text = ""
For i = 1 To 10 '输入原始数据
a(i) = Int(Rnd * 100)
Txtorigin.Text = Txtorigin.Text + Str(a(i)) + "."
Next i
'调用子程序排序并输出中间结果
Call shellsort(10)
End Sub
小结
在进行希尔排序时,需注意增量序列的取值方法,并且使这些序列中的值没有除1之外的公因子,且最后一个增量值必须为1。
能解决问题的办法都是好办法,问题不一定整体解决才好。这就是分治的思想。