需要帮助将方法从递归更改为迭代

时间:2015-02-21 21:51:41

标签: java algorithm recursion stack iteration

我正在研究一个程序,该程序将根据数据和正确数据的哈希来修复数据损坏。即使只处理几个字节的数据,它在大约4或5位被破坏后开始变慢,所以我想我会迭代而不是递归。在做了一些研究之后,我发现我可以使用堆栈来完成这项工作。我目前无法找到正确的位置来弹出堆栈中的变量。这是原始方法。

private static void fixFile(byte[] data, byte[] hash, byte[] correctHash, MessageDigest hasher, long depth)
{
    int len = data.length;
    outer: for(int i = 0; i < len; i++)
    {
        byte origVal = data[i];
        for(int j = 0; j < 8; j++)
        {
            data[i] = (byte) (data[i] ^ (1 << j));

            if(depth > 1)
                fixFile(data, hash, correctHash, hasher, depth - 1);
            hash = hasher.digest(data);

            if(!Arrays.equals(correctHash, hash))
                data[i] = origVal;
            else
                break outer;
        }
    }
}

这是修改后的方法,我试图让它迭代。

private static void fixFile(byte[] data, byte[] hash, byte[] correctHash, MessageDigest hasher, long depth)
{
    Stack stack = new Stack<Integer>();

    int len = data.length;
    outer: for(int i = 0; i < len; i++)
    {
        byte origVal = data[i];
        for(int j = 0; j < 8; j++)
        {
            data[i] = (byte) (data[i] ^ (1 << j));

            if(depth > 1)
            {
                stack.push(depth);
                stack.push(i);
                stack.push(j);
                depth--;
                i = -1;
                j = 0;
                continue outer;
            }
            else
            {
                // where do I put this to make it work.
                j = stack.pop();
                i = stack.pop();
                depth = stack.pop();
            }
            hash = hasher.digest(data);

            if(!Arrays.equals(correctHash, hash))
                data[i] = origVal;
            else
                break outer;
        }
    }
}

1 个答案:

答案 0 :(得分:0)

我认为你的递归方法对于这个问题是理想的,所有的时间都将用在摘要函数中。

但是,当您修复深度位时,您可以在程序速度上获得因子(深度)改进。 (因此,对于6位,这将使程序变为6 * 5 * 4 * 3 * 2 * 1 =快720倍。)

问题是您当前的代码当前切换数据中的深度位,但是按任何顺序。即,当它切换三位时,它将尝试切换位1,2,3和2,1,3和3,1,2和3,2,1以及1,3,2和2,3,1(以及其他许多位)选择)。请注意,在每种情况下,切换完全相同的3位,因此没有必要测试它们。

您可以通过将其他参数传递给代码来说明最后一位被切换的位置(即传入i和j作为i_base和j_base),然后只允许您的代码在以后更换新位时来解决此问题。在数据中的位置(即如果i> i_base ||(i == i_base&amp;&amp; j&gt; j_base))。