Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 如何证明递归算法的正确性 //对从L[i]到L[j]的项目进行排序 无效三向排序(int[]L,int i,int j){ 如果(L[i]>L[j])交换(i,j); 如果(j-i+1>2){ t=(j-i+1)/3; 三向排序(L,i,j-t); 三向排序(L,i+t,j); 三向排序(L,i,j-t); } }_Algorithm - Fatal编程技术网

Algorithm 如何证明递归算法的正确性 //对从L[i]到L[j]的项目进行排序 无效三向排序(int[]L,int i,int j){ 如果(L[i]>L[j])交换(i,j); 如果(j-i+1>2){ t=(j-i+1)/3; 三向排序(L,i,j-t); 三向排序(L,i+t,j); 三向排序(L,i,j-t); } }

Algorithm 如何证明递归算法的正确性 //对从L[i]到L[j]的项目进行排序 无效三向排序(int[]L,int i,int j){ 如果(L[i]>L[j])交换(i,j); 如果(j-i+1>2){ t=(j-i+1)/3; 三向排序(L,i,j-t); 三向排序(L,i+t,j); 三向排序(L,i,j-t); } },algorithm,Algorithm,上面的代码将列表L从最小到最大排序。为了证明这个算法是正确的,我想我们可以用归纳法吗?提示是,调用threewaysort(L,0,L.length-1)实际上有使L排序的副作用 但我目前正陷于归纳法证明的步骤中。你确实可以使用归纳法。让我们使用符号Li,j来表示子数组,其中包含从L[i]到L[j]的项 基本情况 此归纳证明有两种基本情况: j-i+1=1 这意味着Li,j中只有一个元素,因此它已经被排序了。如果条件为true,则两者都不,因此不会发生任何事情:Li,j在调用threewayso

上面的代码将列表L从最小到最大排序。为了证明这个算法是正确的,我想我们可以用归纳法吗?提示是,调用
threewaysort(L,0,L.length-1)
实际上有使L排序的副作用


但我目前正陷于归纳法证明的步骤中。

你确实可以使用归纳法。让我们使用符号Li,j来表示子数组,其中包含从L[i]到L[j]的项

基本情况 此归纳证明有两种基本情况:

  • j-i+1=1

    这意味着Li,j中只有一个元素,因此它已经被排序了。如果条件为true,则两者都不
    ,因此不会发生任何事情:Li,j在调用
    threewaysort(L,i,j)
    后进行排序

  • j-i+1=2

    Li,j中有两个元素。如果尚未排序,则第一个
    If
    条件为true,对
    swap
    的调用将有效地对Li,j进行排序。如果
    条件为false,则第二个
    。所以Li,j在调用
    threewaysort(L,i,j)

  • 诱导步骤 我们得到了j-i+1>2的情形

    现在Li,j中至少有3种元素。归纳证明让我们假设
    threewaysort
    对于较小的子阵列正确工作

    我们暂时忽略可能执行的
    交换
    ,只关注第二个
    的主体(如果
    ),该主体将被执行:

    t保证大于零

    进行了三个递归调用:子数组Li,j-t,Li+t,j,以及Li,j-t

    让我们定义一下:

    A=Li,i+t-1
    B=Li+t,j-t
    C=Lj-t+1,j

    这些是Li,j的非重叠相邻范围。A和C的尺寸都是t。B的大小至少为t(可以是t、t+1或t+2)。 让我们定义加号来表示两个子数组的并集。然后Li,j=A+B+C,递归调用实际上是对A+B,B+C进行排序,然后再对A+B进行排序

    由于t是严格正的,A+B和B+C比A+B+C小,因此我们可以假设这些递归调用成功地对相应的子数组进行排序(归纳前提)

    让我们看看A+B+C中的t最大值会发生什么情况。在第一次递归调用后,不在C中的值将最终在B中(回想一下,B的大小至少是t)。因此,我们确定t最大值都在B+C中。在第二次递归调用之后,我们可以确定所有这些t最大值都只能在C中找到

    A+B+C中的t最小值也会发生类似的情况。在第一次递归调用之后,它们中的任何一个都不能再位于B中,但这并没有真正的帮助。在第二次递归调用之后,它们中的任何一个都不能再使用C语言了。在第三次递归调用之后,它们都不能在B中,因此它们都在A中

    总结一下,我们得到:

    • A被排序(因为在最后一次递归调用之后A+B被排序)
    • B已排序(相同原因)
    • C已排序(因为在第二次递归调用之后,B+C已排序,而在第三次调用期间未触及C)
    • A具有来自A+B+C的最小值
    • C具有A+B+C中的最大值
    • B具有来自A+B+C的剩余值
    这意味着A+B+C被排序

    这就完成了归纳法的证明

    更少的互换 该证明还表明,当数组的大小不同于2时,交换是可选的。因此,代码应该是正确的,如下所示:

    void threewaysort(int[] L, int i, int j) {
        if (j - i + 1 > 2) {
            t = (j - i + 1) / 3;
            threewaysort(L, i, j - t);
            threewaysort(L, i + t, j);
            threewaysort(L, i, j - t);
        } else if (L[i] > L[j]) {
            swap(L, i, j);
        }
    }
    
    然而,执行原始代码中描述的交换平均会导致更少的交换(但更多的比较)

    时间复杂性 首先,我们注意到,除了递归调用之外,所有其他语句都以常量时间执行

    其次,递归调用是在大小大约小三分之一的数组上进行的

    当n=j-i+1时,递推关系为:

    f(n)=3·f((2/3)n)
    f(2)=f(1)=1

    如果我们扩展递归,我们得到:

    f(n)=32·f((2/3)2n)=3k·f((2/3)kn)

    当k的选择使得(2/3)kn=2(或1)时,我们知道f((2/3)kn)=1,并且该系数可以从表达式中省略:

    f(n)=3k

    现在我们必须用n来解析k:

    (2/3)kn=2
    k=log3/2(n/2)
    k=log3(n/2)/log3(3/2)
    k=2.7log3(n/2)

    因此,现在我们有:

    f(n)=3k
    f(n)=(3log3(n/2))2.7
    f(n)=(n/2)2.7

    将时间复杂度设置为:

    f(n)=O(n2.7)


    。。。相当低效的排序算法;效率低于气泡排序。

    您确实可以使用归纳法。让我们使用符号Li,j来表示子数组,其中包含从L[i]到L[j]的项

    基本情况 此归纳证明有两种基本情况:

  • j-i+1=1

    这意味着Li,j中只有一个元素,因此它已经被排序了。如果
    条件为true,则两者都不
    ,因此不会发生任何事情:Li,j在调用
    threewaysort(L,i,j)
    后进行排序

  • j-i+1=2

    Li,j中有两个元素。如果尚未排序,则第一个
    If
    条件为true,对
    swap
    的调用将有效地对Li,j进行排序。如果
    条件为false,则第二个
    。所以Li,j在调用
    threewaysort(L,i,j)

  • 诱导步骤 我们得到了j-i+1>2的情形

    现在有