优化递归计数算法

时间:2016-02-18 20:04:47

标签: c algorithm recursion

我讨厌在这里发布作业帮助,但我已经筋疲力尽了。在C语言中编写一个简单的递归函数时,我遇到了Stack Overflow(至少那是Java中所称的)问题。

我需要n个数的每个r-排列,并且我认为最好的方法是将基数n计算为长度r。

对于少量数字,它可以正常工作,但最高情况(n = 10,r = 6)最终会耗尽内存。我可以很容易地迭代地编写它,但它需要递归。这是我到目前为止所拥有的:

int permute(int *tempArray, int amtNums, int goalLength, int totalMatches) {
    totalMatches += 1; //Temporary, will be replaced by a function later

    printArray(tempArray, goalLength);

    tempArray[0]++;

    int j = 0;
    while(tempArray[j] >= amtNums) {
        tempArray[j+1]++;
        tempArray[j] = 0;
        j++;
    }

    if(j+1 > goalLength) return totalMatches;


    return permute(tempArray, amtNums, goalLength, totalMatches);
}  

对于最大情况被称为permute((int*)calloc(numSlots, sizeof(int)), 10, 6, 0);,n = 10 r = 6

我应该注意:计数并不完全直观,它有点倒退,但会产生我想要的所有数字组合。例如:n = 4,r = 3

0 0 0 
1 0 0 
2 0 0 
3 0 0 
0 1 0 
1 1 0 
2 1 0 
3 1 0 
.....
0 2 3 
1 2 3 
2 2 3 
3 2 3 
0 3 3 
1 3 3 
2 3 3 
3 3 3 

2 个答案:

答案 0 :(得分:1)

我相信您必须修改递归函数才能获得goalLength函数调用堆栈的最大深度。您可以像我在这里一样添加参数depth

int permute( int *tempArray, int amtNums, int goalLength, int depth, int totalMatches) {
    int i;

    if ( depth < goalLength - 1) {
        for ( i = 0; i < amtNums; ++i ) {
            tempArray[depth] = i;
            totalMatches = permute(tempArray, amtNums, goalLength, depth + 1, totalMatches);
        }
    } else {
        for ( i = 0; i < amtNums; ++i ) {
            tempArray[depth] = i;
            printArray(tempArray, goalLength);
            ++totalMatches;
        }
    }

    return totalMatches;
}

您当然可以重写它,将for循环放在外面,if放在里面。我用这个小测试程序尝试了这个代码:

#include <stdio.h>

#define NDIGIT 4
#define NLENGTH 3

void printArray( int *temp, int size ) {
    int i;

    for ( i = 0; i < size; ++i ) {
        printf("%d ", temp[i]);
    }
    printf("\n"); 
}

int permute( int *tempArray, int amtNums, int goalLength, int depth, int totalMatches);

int main(void) {
    int results[NLENGTH];
    int n = permute(results, NDIGIT, NLENGTH, 0, 0);

    printf("Total number of permutations: %d\n", n);

    return 0;
}

NDIGIT设置为10,将NLENGTH设置为6并注释掉打印功能(如果您需要,可以保留...)程序正常运行输出是:

Total number of permutations: 1000000

答案 1 :(得分:0)

你的函数使用对自身的尾调用,编译器应该能够将这种递归转换为循环。使用命令行选项-O3或IDE提供的任何内容启用优化。如果编译器实现递归,则函数将递归 amtNums goalLength ,这是n = 10且r = 6的大数字: 1 000 000 递归级别可能导致 Stack Overflow