使用组合改进软件测试用例的生成2

从这个例子你可以看到我需要建立某种组合,给定条目总数和子集大小来计算全部组合元素的总数,并且确定某个特定组合元素的后继者以便我能列出所有组合元素。

  稍微细致地考察这些例子,你可以看到组合有两个重要的特性:条目的总数(数学上通常用 n 表示)和子集的大小(通常用 k 表示)。数学组合可以是 0 基 (0-based)或 1 基(1-based)的。我将在这个专栏中通篇使用 0 基计数制,并且分别使用 n 和 k 表示条目总数和在子集中的 条目数。

  在我的例子中迄今我已列出的组合元素用的是词典顺序(有时称为字典顺序)。对于数学组合来说,如果以整数来说明,这意味着元素是用增序列出。举个例子,如果 n = 5,k = 3,第一个元素是{ 0, 1, 2 },那么紧接着的元素是{ 0, 1, 3 },因为12后面是13。还要注意某一组合元素的原子(单个整数)也呈现增序 形式,所以这里有一种双重排序状态。

  组合的一个重要的函数是对于特定 n 和 k 值的组合元素总数。这个函数大多被称为 Choose。因此在第一个例子中有 5 个人名的 情况下,我将其写成 Choose(5,3) = 10,也就是一次从5个条目中选出3个,那么共有10个组合元素。你可能会碰到另外一些标识和命名 Choose 函数的方法,特别是在数学论文中,但 本文我总是使用 Choose。

  组合中的 n 和 k 与 Choose 函数中的 n 和 k 是非常容易混淆的。n = 7,k = 4 的数学组合(在7个条目中一次取4个) ,其中有象 { 0, 3, 4, 6 } 这样的元素,而 Choose(7,4) 函数则返回 35,这是从7个条目中一次取4个的组合元素总数。

  组合经常会和排列搞混淆,排列是一组条目所有的可能排列,这时顺序是重要的。如果说你有姓名 Alex、Bill、Cris 和 Doug。用词典顺序排列的 话,前三个排列是:{ Alex, Bill, Cris, Doug },{ Alex, Bill, Doug, Cris } 和 { Alex, Cris, Bill, Doug }。

  一个组合类

  数学组合非常适宜用一个类来实现。你需要数据成员存储 n 的值(条目总数),k(每个子集元素的条目个数)的值,以及一个数组来保存每个组合元素的“原子”。Figure 3 是表述某个Combination(组合)对象的基本代码和创建该组合对象第一个词典元素的构造函数,以及将它表示为一个字符串的代码。我决定使用C#,但你可以 轻松地将它改编为你所选的任意一种基于 .NET的编程语言。

  我将这个代码放入类库(Class Library)编译后,我可以给它增加一个工程选项参数(Project Reference),并从 .NET 控制台 程序调用它,就象我在此所做的这样:

  Combination c = new Combination(5,3);Console.WriteLine("/nCombination c(5,3) is initially " + c.ToString());

  下面的输出将显示在屏幕上:

  Combination c(5,3) is initially { 0 1 2 }

  当组合类的构造函数进行如下调用时:

  Combination c = new Combination(5,3);
我在内存中获得一个对象,它表示五个条目中一次取三个的最初的词典排序的数学组合元素。

  构造函数代码创建最初的组合元素时是相当简单的。两个代表条目总数和子集大小的参数被分别存储在数据成员 n 和 k 中。因为我处理的数值可能会很大, 所以我决定使用 C# 的 long 类型代替int 类型。如果我愿意的话,我可以用 ulong 类型(无符号 long)获得双倍的数值范围。我用子集的大小 k 来为一个 long 类型的命名数组分配空间,然后用 0 到 k-1 范围的整数填充每个数据单元。

posted @ 2008-07-14 16:13  广陵散仙(www.cnblogs.com/junzhongxu/)  阅读(136)  评论(0编辑  收藏  举报