简体   繁体   English

递归方法java的问题

[英]Trouble with recursive method java

basically I have a brute force password guesser(I realize it's not very efficient) I have a process I want to make into a recursive method that i can pass a length integer and it will run with that amount of characters. 基本上,我有一个蛮力密码猜测器(我意识到这不是很有效),我有一个过程要做成递归方法,我可以传递一个长度整数,并且它将以该数量的字符运行。 here is the code: 这是代码:

public static void generatePassword(int length)
{
    // should be a recusive function learn how to do that
    // 1 interval
    for(int i =32;i<127;i++)// ascii table length
    {
                System.out.println((char)i);

    }
    // 2 interval
    for(int z =32;z<127;z++)// ascii table length
    {
        for(int q =32;q<127;q++)// ascii table length
        {
            System.out.println((char)z+""+(char)q);

        }

    }
    // 3 interval
    for(int w =32;w<127;w++)// ascii table length
    {
        for(int o =32;o<127;o++)// ascii table length
        {
            for(int g =32;g<127;g++)// ascii table length
            {
            System.out.println((char)w+""+(char)o+""+(char)g);
            }
        }


    }

}

the intervals return a string with that length example: 3rd interval will return every possible string combination with a length of 3. if anyone can help me automate this process and explain(i would like to learn rather then copy and paste) that would be great ! interval返回具有该长度示例的字符串:3rd interval将返回长度为3的每个可能的字符串组合。如果有人可以帮助我使此过程自动化并进行解释(我想学习而不是复制和粘贴),那会很棒! :) :)

A recursive method is a method that calls itself, it has a base-condition (also called stop condition) which prevents it from going into an infinite loop. 递归方法是一种调用自身的方法,它具有基本条件(也称为停止条件),可防止其进入无限循环。

Lets take the first interval as an example: 让我们以第一个间隔为例:

for(int i = 32; i < 127; i++) { // ascii table length
    System.out.println((char)i);
}

we can create a recursive method that'll do the same thing: 我们可以创建一个将执行相同操作的递归方法:

private void interval1(int i) {
    if (i < 32 || i >= 127) return;
    System.out.println((char)i);
    interval1(i + 1);
}

in order to use it for our use-case, we should call this method with i=32: interval(32) 为了在我们的用例中使用它,我们应该使用i = 32调用此方法: interval(32)

Hope this helps! 希望这可以帮助!

Here is your method implemented using recursion: 这是您使用递归实现的方法:

public static void generatePassword(int length, String s) {
        if (length == 0) {
            System.out.println(s);
            return;
        }
        for (int i = 32; i < 127; i++) {
            String tmp  = s+((char) i);
            generatePassword(length - 1, tmp);
        }
    }

All you have to do is to pass length and initial String (ie "") to it. 您要做的就是将长度和初始字符串(即“”)传递给它。
At if statement there is checked, if recursion should be stopped (when length of generated password is equals to expected). 在if语句处,检查是否应停止递归(当生成的密码的长度等于预期的长度时)。
At for-loop there is new character added to actual String and the method is invoked with shorter length and a new String as an argument. 在for循环中,将新字符添加到实际的String中,并以较短的长度和新的String作为参数来调用该方法。

Hope it helps. 希望能帮助到你。

The function 功能

Note that this will be EXTREMELY INEFFICIENT. 请注意,这将是极其无效的。 This shouldn't ever be done in practice, since the number of String objects created is MIND-BOGGLINGLY HUGE (see bottom of answer) 这实际上不应该做,因为创建的String对象的数量是MIND-BOGGLINGLY HUGE(请参阅答案底部)

public void recursivePrint(String prefix, int levels) {
    if (levels <= 1) {
        for (int i = 33; i < 127; ++i) {
            System.out.println(prefix+(char)i);
        }
    } else {
        for (int i = 33; i < 127; ++i) {
            recursivePrint(prefix+(char)i, levels-1);
        }
    }
}

Then you call it with: 然后用以下命令调用它:

recursivePrint("", 5); // for printing all possible combinations of strings of length 5

The way it works 工作方式

Each call to a function has it's own memory, and is stored seperately. 每个对函数的调用都有其自己的内存,并且分别存储。 When you first call the function, there is a String called prefix with a value of "", and an int called 'levels' which has a value of 5. Then, that function calls recursivePrint() with new values, so new memory is allocated, and the first call will wait until this new call has finished. 首次调用该函数时,有一个名为prefix的字符串,其值为“”,以及一个名为'levels'的整数,其值为5。然后,该函数使用新值调用recursivePrint(),因此新的内存为已分配,则第一个呼叫将等待,直到此新呼叫结束。

This new call has a String called prefix with a value of (char)34+"" , and a levels with a value of 4. Note that these are completely separate instances of these variables to the first function call because remember: each function call has it's own memory (the first call is waiting for this one to finish). 这个新调用具有一个称为String的String,其前缀为(char)34+"" ,而一个级别的值为4。请注意,对于第一个函数调用,这些变量是这些变量的完全独立的实例,因为请记住:每个函数调用有它自己的内存(第一个调用正在等待该调用完成)。 Now this second call makes another call to the recursivePrint() function, making more memory, and waiting until this new call finishes. 现在,第二个调用再次调用recursivePrint()函数,从而增加了内存,并等待该新调用完成。

When we get to levels == 1, there is a prefix built up from previous calls, and all that remains is to use that prefix and print all the different combinations of that prefix with the last character changing. 当级别达到== 1时,先前的调用会建立一个前缀,剩下的就是使用该前缀并打印该前缀的所有不同组合以及最后更改的字符。

Recursive methods are highly inefficient in general, and in this case especially. 递归方法通常效率很高,尤其是在这种情况下。

Why you should never use it 为什么不应该使用它

This method is not just inefficient, though; 但是,这种方法不仅效率低下,而且效率很高。 it's infeasible for anything useful. 任何有用的东西都是不可行的。 Let's do a calculation: how many different possibilities are there for a string with 5 characters? 让我们做一个计算:一个5个字符的字符串有多少种不同的可能性? Well there's 127-33=94 different characters you want to choose, then that means that you have 94 choices for each character. 好吧,您要选择127-33 = 94个不同的字符,这意味着每个字符有94个选择。 Then the total number of possibilities is 94^5 = 7.34*10^9 [that's not including the 5+ bytes to store each one] (to put that in perspective 4GB of RAM is around 4*10^9 bytes) 然后,可能性总数为94 ^ 5 = 7.34 * 10 ^ 9 [这不包括5个以上的字节来存储每个字节](将其视为4GB RAM大约为4 * 10 ^ 9字节)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM