合并排序的这种实现是否使用相互递归?

时间:2017-06-07 21:50:34

标签: javascript sorting recursion mergesort mutual-recursion

这个mergeSort算法是否使用相互递归?我意识到mergeSort调用merge函数并调用自身(mergeSort),但由于merge不调用mergeSort,因此它不是相互递归而是简单只是递归?

function mergeSort(arr) {
    // split array
    ...
    return merge(mergSort(firstHalf), mergeSort(secondHalf));
}

function merge (array1, array2) {
    // merge both arrays
    ...
    return singleArray;
}

2 个答案:

答案 0 :(得分:1)

正确:这是简单的递归。相互递归也称为间接递归:A调用B; B呼叫A。

您的分析完全正确:merge调用mergeSort然后您将进行相互递归。在发布的代码中,对merge的调用是调用树上的简单父子链接。

答案 1 :(得分:1)

为了跟进关于合并排序的相互递归的解释,它是用于优化自顶向下合并排序以避免合并期间的复制步骤的方法之一,其中合并的方向取决于递归的级别。替代方法是将标志作为合并方向的参数传递。在下面的示例代码中,a []是原始数组,b []是工作数组。 TopDownSplitMergeAtoA返回原始数组中的排序数据,TopDownSplitMergeAtoB返回工作数组中的排序数据,TopDownSplitMergeAtoA调用TopDownSplitMergeAtoB,反之亦然(这是相互递归)。如果子数组大小为TopDownSplitMergeAtoB的一个,则发生唯一的复制操作,在这种情况下,一个元素从原始数组复制到工作数组。

void TopDownSplitMergeAtoA(int a[], int b[], size_t ll, size_t ee);
void TopDownSplitMergeAtoB(int a[], int b[], size_t ll, size_t ee);
void Merge(int a[], int b[], size_t ll, size_t rr, size_t ee);

void MergeSort(int a[], size_t n)       // entry function
{
    if(n < 2)                           // if size < 2 return
        return;
    int *b = new int[n];
    TopDownSplitMergeAtoA(a, b, 0, n);
    delete[] b;
}

void TopDownSplitMergeAtoA(int a[], int b[], size_t ll, size_t ee)
{
    if((ee - ll) == 1)                  // if size == 1 return
        return;
    size_t rr = (ll + ee)>>1;           // midpoint, start of right half
    TopDownSplitMergeAtoB(a, b, ll, rr);
    TopDownSplitMergeAtoB(a, b, rr, ee);
    Merge(b, a, ll, rr, ee);     // merge b to a
}

void TopDownSplitMergeAtoB(int a[], int b[], size_t ll, size_t ee)
{
    if((ee - ll) == 1){                 // if size == 1 copy a to b
        b[ll] = a[ll];
        return;
    }
    size_t rr = (ll + ee)>>1;           // midpoint, start of right half
    TopDownSplitMergeAtoA(a, b, ll, rr);
    TopDownSplitMergeAtoA(a, b, rr, ee);
    Merge(a, b, ll, rr, ee);     // merge a to b
}

void Merge(int a[], int b[], size_t ll, size_t rr, size_t ee)
{
    size_t o = ll;                      // b[]       index
    size_t l = ll;                      // a[] left  index
    size_t r = rr;                      // a[] right index
    while(1){                           // merge data
        if(a[l] <= a[r]){               // if a[l] <= a[r]
            b[o++] = a[l++];            //   copy a[l]
            if(l < rr)                  //   if not end of left run
                continue;               //     continue (back to while)
            while(r < ee)               //   else copy rest of right run
                b[o++] = a[r++];
            break;                      //     and return
        } else {                        // else a[l] > a[r]
            b[o++] = a[r++];            //   copy a[r]
            if(r < ee)                  //   if not end of right run
                continue;               //     continue (back to while)
            while(l < rr)               //   else copy rest of left run
                b[o++] = a[l++];
            break;                      //     and return
        }
    }
}