【问题标题】:Finding all possible words from inputted character arrays (permutations)从输入的字符数组(排列)中查找所有可能的单词
【发布时间】:2013-09-26 13:12:56
【问题描述】:

在阅读了几篇文章后,我仍然对排列和递归函数感到困惑。我正在尝试在不等长的 2D 数组中创建所有可能的 3 个字母排列,其中第一个字母来自集合 {'l'、'm'、'n'},第二个字母来自集合 {'q ', 'r'} 和第三个字母来自集合 {'a', 'e', 'i', 'o'}。我的代码通过了正确的排列模式,但没有打印出正确的输出。例如,如果前 8 个排列应该是:

lqa
lqe
lqi
lqo
lra
lre
lri
lro

我的代码打印出来:

lqa
e
i
o
ra
e
i
o

对问题所在有什么想法吗?以下是我的代码的相关部分:

rec(character_pools,0,3);
void rec(char** pool, int k, int j)
{
    if(k==j)
    {
        printf("\n");
        return;
    }
    int i,len=strlen(pool[k]);
    for (i=0;i<len;i++)
    {
        printf("%c",pool[k][i]);
        rec(pool,k+1,j);
    }
}

【问题讨论】:

  • 你没有调试器吗?
  • 是的,我正在使用 VS2010 进行调试,但我对调试递归调用不是很精通。我可以更容易地手工完成它们。这里的问题是我知道缺少什么,但我不知道在哪里插入“缺少的循环”来填充数组的未更改部分。我尝试在任何地方插入它都会使程序因尝试访问越界数组或打印非字母数字字符而崩溃。如果您问我,这是非常奇怪的行为,但是当我学习递归时,我希望它开始对我有意义。

标签: c arrays recursion permutation


【解决方案1】:

这最终对我有用!谢谢@Tsukuyo 的提示。如果我想在排列中找到字符串的第 n 个索引,是否需要单独提出一个问题?

void rec(char** pool, int k, int j, char* cur, int counter)
{
    if(k==j)
    {
        cur[k]=0;
        printf("Recursive call #%d %s\n",counter,cur);
        return;
    }
    int i,len=strlen(pool[k]);


    for (i=0;i<len;i++)
    {
        cur[k]=pool[k][i];
        rec(pool,k+1,j,cur,counter++);
    }
}

【讨论】:

  • 您最好提出一个新问题并附上此问题的链接。
【解决方案2】:

调用栈:

   rec(pool, 0, 3);
-> 'l'   rec(pool, 1, 3);
      -> 'q'   rec(pool, 2, 3);
            -> 'a'   rec(pool, 3, 3);
                  -> '\n'
            -> 'e'   rec(pool, 3, 3);
                  -> '\n'
            -> 'i'   rec(pool, 3, 3);
                  -> '\n'
            -> ...
      -> ...
-> ...

更新:
不像递归那样。但是..它有效:)。希望这会有所帮助。
假设最大长度为 10。

#include <stdio.h>
#include <string.h>
#define ALL_DONE 1
#define NOT_YET  0

int rec(char (*pool)[10], int num, int start);

int main(void)
{
    int i, num;
    char pool[20][10];

    scanf("%d", &num);
    for (i = 0; i < num; i++){
        scanf("%s", pool[i]);
    }
    while ( !rec(pool, num, 0) );  // keepint calling until all permutations are printed
    return 0;
}

int rec(char (*pool)[10], int num, int start)
{
    static int ndx[20] = {0};  // record the index of each string

    if (start == num){
        printf("\n");
        return ALL_DONE;
    }
    printf("%c", pool[start][ndx[start]]);
    if ( rec(pool, num, start+1) == ALL_DONE ){
        ndx[start+1] = 0;
        ndx[start]++;
        if (ndx[start] == strlen(pool[start])){
            return ALL_DONE;
        return NOT_YET;
    }
    return NOT_YET;
}

解释:

   rec(pool, 0, 0)[1st calling]     
-> 'l'   rec(pool, 1, 0)                    | ndx[0..2] = 0, 0, 0
      -> 'q'   rec(pool, 2, 0)              | ndx[0..2] = 0, 0, 0
            -> 'a'   rec(pool, 3, 0)        | ndx[0..2] = 0, 0, 0
                  -> '\n' retrun ALL_DONE   | ndx[0..2] = 0, 0, 0
            -> return NOT_YET               | ndx[0..2] = 0, 0, 1
      -> return NOT_YET                     | ndx[0..2] = 0, 0, 1
-> return NOT_YET                           | ndx[0..2] = 0, 0, 1
|
   rec(pool, 0, 0)[2nd]
-> 'l'   rec(pool, 1, 0)                    | ndx[0..2] = 0, 0, 1
      -> 'q'   rec(pool, 2, 0)              | ndx[0..2] = 0, 0, 1
            -> 'e'   rec(pool, 3, 0)        | ndx[0..2] = 0, 0, 1
                  -> '\n' return ALL_DONE   | ndx[0..2] = 0, 0, 1
            -> return NOT_YET               | ndx[0..2] = 0, 0, 2
      -> return NOT_YET                     | ndx[0..2] = 0, 0, 2
-> return NOT_YET                           | ndx[0..2] = 0, 0, 2
|
|  ...
|
   rec(pool, 0, 0)[4th]
-> 'l'   rec(pool, 1, 0)                    | ndx[0..2] = 0, 0, 3
      -> 'q'   rec(pool, 2, 0)              | ndx[0..2] = 0, 0, 3
            -> 'o'   rec(pool, 3, 0)        | ndx[0..2] = 0, 0, 3
                  -> '\n' return ALL_DONE   | ndx[0..2] = 0, 0, 3
            -> return ALL_DONE              | ndx[0..2] = 0, 0, 4
      -> return NOT_YET                     | ndx[0..2] = 0, 1, 0
-> return NOT_YET                           | ndx[0..2] = 0, 1, 0
|
| ...
| ...
|
   rec(pool, 0, 0)[5th]
-> 'l'   rec(pool, 1, 0)                    | ndx[0..2] = 0, 1, 0
      -> 'r'   rec(pool, 2, 0)              | ndx[0..2] = 0, 1, 0
            -> 'a'   rec(pool, 3, 0)        | ndx[0..2] = 0, 1, 0
                  -> '\n' return ALL_DONE   | ndx[0..2] = 0, 1, 0
            -> return NOT_YET               | ndx[0..2] = 0, 1, 1
      -> return NOT_YET                     | ndx[0..2] = 0, 1, 1
-> return NOT_YET                           | ndx[0..2] = 0, 1, 1
|
| ...
|
   rec(pool, 0, 0)[8th]
-> 'l'   rec(pool, 1, 0)                    | ndx[0..2] = 0, 1, 3
      -> 'r'   rec(pool, 2, 0)              | ndx[0..2] = 0, 1, 3
            -> 'o'   rec(pool, 3, 0)        | ndx[0..2] = 0, 1, 3
                  -> '\n' return ALL_DONE   | ndx[0..2] = 0, 1, 3
            -> return ALL_DONE              | ndx[0..2] = 0, 1, 4
      -> return ALL_DONE                    | ndx[0..2] = 0, 2, 0
-> return ALL_DONE                          | ndx[0..2] = 1, 0, 0
|
| FINISH

【讨论】:

  • 正确,这就是我在纸上追踪它的方式。我知道我需要一个 for (i=0;i
  • 对不起我
  • @JohnR 我认为使用递归解决问题不是一个好主意。递归只会让事情变得更复杂。嵌套循环更适合这个问题。
  • 每个作业都需要它。此外,“每个输入案例的第一行将包含一个正整数 m(m ≤ 20),即密码的长度。接下来的 m 行将包含按字母顺序排列的不同小写字母字符串,代表每个可能的密码中每个字母的字母。所以我可能会得到 20 个嵌套循环。:/ 没有 bueno
【解决方案3】:

您创建一个 char 数组,其中包含您要使用的字符串 char str[] = "ABC";

然后你得到字符串 int n = strlen(str); 的长度,最后你排列。

您创建了一个新函数,该函数将包含输入字符串、字符串的起始索引和字符串的结束索引。 检查起始索引 (int s) 是否等于结束索引 (int e) 如果是,这意味着你已经完成了,如果不是,你进入一个循环,你从 start (s) 到 end (e),交换值,递归,再次交换到回溯。

C++ 中的一个例子:

#include <stdio.h>
#include <string.h>

void swap(char *i, char *j)
{
    char temp;
    temp = *i;
    *i = *j;
    *j = temp;
}

void permutate(char *str, int start, int end)
{
    int i;
    if (start == end)
        printf("%s\n", str);
    else
    {
        for (i = start; i <= end; i++)
        {
            swap((str + start), (str + i));
            permutate(str, start + 1, end);
            swap((str + start), (str + i)); //backtrack
        }
    }
}

int main()
{
    char str[] = "ABC";
    int n = strlen(str);
    permutate(str, 0, n - 1);
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-18
    • 2015-12-31
    • 1970-01-01
    • 2013-04-13
    • 1970-01-01
    • 2016-04-06
    相关资源
    最近更新 更多