Swift 中的值与引用类型,以 Wikipedia 实现堆的排列算法为例

Posted

技术标签:

【中文标题】Swift 中的值与引用类型,以 Wikipedia 实现堆的排列算法为例【英文标题】:Value vs Reference Types in Swift using Wikipedia implementation of Heap's permutation algorithm as example 【发布时间】:2021-07-05 17:35:40 【问题描述】:

我试图编写代码来确定排列。在 Wikipedia 中有一个简单算法的伪代码(来自 BR Heap)。我试图翻译伪代码

procedure generate(k : integer, A : array of any):
    if k = 1 then
        output(A)
    else
        // Generate permutations with kth unaltered
        // Initially k == length(A)
        generate(k - 1, A)

        // Generate permutations for kth swapped with each k-1 initial
        for i := 0; i < k-1; i += 1 do
            // Swap choice dependent on parity of k (even or odd)
            if k is even then
                swap(A[i], A[k-1]) // zero-indexed, the kth is at k-1
            else
                swap(A[0], A[k-1])
            end if
            generate(k - 1, A)

        end for
    end if

我的代码给出了正确的排列数量,但我可以看到有一些缺失,而另一些则加倍。

事实证明这是基于我对 Swift 值类型与引用类型的误解。

这是我的(不能正常工作)代码:

func perms(k: Int, arr: [Any])    //NOTE that this is NOT providing the correct permuations at this time.  Some are doubled, some are missing (Yet the total permuations in number are correct)
    var variedArray = arr
    if k == 1 
        counter += 1  //this is not part of the Wikipedia psuedo code, I just wanted to count that I was at least getting the right number of permutations
        outputArray.append(variedArray)  //this is appending to an array that contains all the permutation after all is done
        
     else 
        
        perms(k: k - 1 , arr: variedArray)
        for i in 0..<k-1 
            if (k)%2 == 0   // if even do this
                variedArray.swapAt(i, k-1)
             else 
                variedArray.swapAt(0, k-1)
            
            perms(k: k - 1, arr: variedArray)
        
    
    
    return

【问题讨论】:

我们并不真正对 Stack Overflow 上的算法进行审查。您应该在代码审查论坛上发布此内容。 谢谢马特,我没有意识到这一点。我会把它移到那里去。 别担心,但请检查下面我的答案,它可能对你有用(或没有) 这确实有一定的意义,尤其是。如果关于inout 的线索确实是问题所在。 【参考方案1】:

这不是我真正喜欢的东西,但在我看来,问题在于 Swift 数组是按值传递的,所以这里需要一个 inout 参数。所以我是这样翻译的:

func generate<T>(k:Int, a: inout Array<T>) 
    if k == 1 
        print(a)
        return
    
    generate(k:k-1, a:&a)
    for i in 0..<k-1 
        if k%2 == 0 
            a.swapAt(i, k-1)
         else 
            a.swapAt(0, k-1)
        
        generate(k:k-1, a:&a)
    

这是我的测试:

    var arr = [1,2,3]
    generate(k:arr.count, a:&arr)

结果在我看来是正确的,但请看你的想法。

【讨论】:

以上是关于Swift 中的值与引用类型,以 Wikipedia 实现堆的排列算法为例的主要内容,如果未能解决你的问题,请参考以下文章

Swift 中的值类型与引用类型

《javascript高级程序设计》学习笔记 | 4.1.原始值与引用值

我的OOP学习笔记值与引用语义类型

无法调用非函数类型“((UInt)->数据?)!”的值与 Alamofire 4

JS浅谈原始值与引用值操作

[Javascript] JavaScript赋值时的传值与传址