【问题标题】:Varying initializer in a 'for loop' in C++在 C++ 中的“for循环”中改变初始值设定项
【发布时间】:2016-03-24 13:29:35
【问题描述】:
int i = 0;
for(; i<size-1; i++) {
    int temp = arr[i];
    arr[i] = arr[i+1];
    arr[i+1] = temp;
}

这里我从数组的第一个位置开始。如果在循环之后我需要再次执行 for 循环,其中 for 循环从数组的下一个位置开始,该怎么办?

赞第一个for loop 起始于:Array[0]

第二次迭代:数组[1]

第三次迭代:数组[2]

例子:

对于数组:1 2 3 4 5

对于 i=0:2 1 3 4 5、2 3 1 4 5、2 3 4 1 5、2 3 4 5 1

对于 i=1:1 3 2 4 5、1 3 4 2 5、1 3 4 5 2 依此类推。

【问题讨论】:

  • 这称为嵌套 for 循环。
  • 了解更多信息:我正在使用的代码:link
  • 你想达到什么目的?您要求一种方法来测试数组或列表之前是否已排序:stackoverflow.com/questions/35989316stackoverflow.com/questions/35867423 — 您是否正在生成数组的所有可能排列以找到已排序的排列?
  • 对您的代码的一些批评:例如,您应该改掉使用int arr[] 参数的习惯,改用int* arrint arr[size] 不标准;不是通过new 分配的数组必须有一个常量作为它们的大小。 std::vector 在这里更适合你。
  • @CiaPan 完全正确!!!。你有什么想法可以实现吗?

标签: c++ arrays sorting


【解决方案1】:

您可以将循环相互嵌套,包括让内循环访问外循环的迭代器值的能力。因此:

for(int start = 0; start < size-1; start++) {
    for(int i = start; i < size-1; i++) {
        // Inner code on 'i'
    }
}

将使用增加的start 值重复您的循环,从而使用更高的i 初始值重复,直到您完成您的列表。

【讨论】:

    【解决方案2】:

    假设您有一个例程来生成给定长度 n 的数组元素的所有可能排列。假设例程在处理完所有 n! 个排列后,将数组的 n 个项按其初始顺序保留。

    问题:我们如何构建一个例程来对具有 (n+1) 个元素的数组进行所有可能的排列?

    答案:
    生成初始n个元素的所有排列,每次处理整个数组;这样,我们处理了所有 n! 个具有相同最后一项的排列。
    现在,将 (n+1)-st 项与其中一个 n 交换并重复排列 n 元素——我们得到另一个 n! 个排列与新的最后一项。
    n 元素按之前的顺序保留,因此将最后一项放回其初始位置并选择另一个放在数组末尾。重复排列 n 个项目。
    以此类推。

    请记住,在每次调用后,例程都会按照初始顺序保留 n-items 数组。为了在 n+1 处保留这个属性,我们需要确保在 (n+1)-st 迭代之后,相同的元素最终被放置在数组的末尾。 n! 个排列。

    你可以这样做:

    void ProcessAllPermutations(int arr[], int arrLen, int permLen)
    {
        if(permLen == 1)
            ProcessThePermutation(arr, arrLen);         // print the permutation
        else
        {
            int lastpos = permLen - 1;                  // last item position for swaps
    
            for(int pos = lastpos; pos >= 0; pos--)     // pos of item to swap with the last
            {
                swap(arr[pos], arr[lastpos]);           // put the chosen item at the end
                ProcessAllPermutations(arr, arrLen, permLen - 1);
                swap(arr[pos], arr[lastpos]);           // put the chosen item back at pos
            }
        }
    }
    

    下面是例程运行的示例:https://ideone.com/sXp35O

    但是请注意,这种方法非常无效:

    1. 它可能在合理的时间内仅适用于非常小的输入大小。排列的数量是数组长度的阶乘函数,它的增长速度比指数增长快,这使得测试的数量确实BIG
    2. 例程没有短返回。即使第一个或第二个排列是正确的结果,例程也会执行所有其余的 n! 个不必要的测试。当然可以添加一个返回路径来中断迭代,但这会使代码有些难看。而且它不会带来显着的收益,因为例程必须平均进行 n!/2 次测试。
    3. 每个生成的排列都出现在递归的最后一级深处。测试正确结果需要从ProcessAllPermutations 中调用ProcessThePermutation,因此很难用其他函数替换被调用者。每次您需要另一种测试/处理/其他方法时,都必须修改调用者函数。或者必须提供一个指向处理函数的指针(“回调”)并将其向下推到所有递归,向下推到将发生调用的地方。这可能是由某个上下文对象中的虚函数间接完成的,因此看起来相当不错 - 但无法避免将额外数据传递到递归调用的开销。
    4. 该例程还有另一个有趣的特性:它不依赖于数据值。永远不会比较数组的元素。这有时可能是一个优势:例程可以置换任何类型的对象,即使它们不可比较。另一方面,它无法检测到重复项,因此在相同项目的情况下,它会产生重复的结果。在所有 n 个相等项的退化情况下,结果将是 n! 个相等序列。

    因此,如果您问如何生成所有排列以检测已排序的排列,我必须回答:不要。
    请务必学习有效的排序算法。

    【讨论】:

    • 这就是我真正想要的,生成所有排列以检测排序的。
    猜你喜欢
    • 2019-09-27
    • 1970-01-01
    • 2012-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-28
    • 2011-04-02
    相关资源
    最近更新 更多