插入排序>通过引用传递的数组中的不可变值的问题

时间:2016-10-24 17:56:55

标签: c++ arrays swift sorting

在插入排序的嵌套循环期间,通过引用传递的swift数组没有正确解包问题。

// - C ++ WORKS -

//在C ++中,此函数已经过测试并且可以正常工作:

struct moveRecord
{
    int fromSquare;
    int toSquare;
    int capturedPiece;
    int moveScore;
};

struct moveRecord m1 = {20, 28, 4, 0};
struct moveRecord m2 = {20, 29, 5, 0};
struct moveRecord m3 = {20, 30, 1, 0};
struct moveRecord m4 = {20, 31, 2, 0};
struct moveRecord m5 = {20, 32, 3, 0};
moves[0] = m1;
moves[1] = m2;
moves[2] = m3;
moves[3] = m4;
moves[4] = m5;

movesStr = moves2Str( moves, numMoves );
cout << "UNSORTED: " << movesStr << endl;

sortMoves( moves, numLegalMoves );

movesStr = moves2Str( moves, numMoves );
cout << "SORTED: " << movesStr << endl;


void sortMoves( moveRecord moves[], int numMoves )
{
    int i, j;
    struct moveRecord tempMove;

    for (j=1; j<numMoves; j++) {
        cout << "j=" << j << " of " << numMoves << endl;
        tempMove = moves[j];
        for (i=j-1; i>-1; i--) {
            cout << "  i=" << i << endl;
            // need to compare abs() values, or else black & white get sorted differently
            if ( abs(moves[i].capturedPiece) >= abs(tempMove.capturedPiece) ) {cout << "break" << endl; break;}
            moves[i+1] = moves[i];
            }
            cout << "we are out of iLoop" << endl;
        moves[i+1] = tempMove;
        }
    return;
}

在XCode日志中包含以下结果:

UNSORTED: e4.4 f4.5 g4.1 h4.2 a5.3
j=1 of 5
  i=0
we are out of iLoop
j=2 of 5
  i=1
break
we are out of iLoop
j=3 of 5
  i=2
  i=1
break
we are out of iLoop
j=4 of 5
  i=3
  i=2
  i=1
break
we are out of iLoop
SORTED:  f4.5 e4.4 a5.3 h4.2 g4.1

数组元素排序为:.4 .5 .1 .2 .3
到正确的顺序:.5 .4 .3 .2 .1
大! C ++正在做正确的事情。

// - SWIFT结果差异 -

func sortMoves( theMoves: inout [moveRecord])
{
    var i : Int = 0
    var j : Int = 0
    var tempMove : moveRecord
    let numMoves : Int = theMoves.count

    for j in 1..<numMoves {
        print("j=\(j) of \(numMoves)")
        tempMove = theMoves[j]
        for i in stride(from:j-1, through:0, by:-1) {
            print("  i=\(i)")
            // need to compare abs() values or black/white sort differently
            if ( abs(theMoves[i].capturedPiece!) >= abs(tempMove.capturedPiece!) ) {print("break"); break}
            theMoves[i+1] = theMoves[i]
            }
        print("we are out of iLoop")
        theMoves[i+1] = tempMove
        }

    return
}

在XCode日志中包含以下结果:

Unsorted Moves: f4.4  g4.5  h4.1  a5.2  b5.3
j=1 of 5
  i=0
we are out of iLoop
j=2 of 5
  i=1
break
we are out of iLoop
j=3 of 5
  i=2
  i=1
  i=0
break
we are out of iLoop
j=4 of 5
  i=3
  i=2
  i=1
  i=0
break
we are out of iLoop
Sorted Moves: f4.4  b5.3  a5.2  h4.1  h4.1

所以数组元素排序为:.4 .5 .1 .2 .3 错误序列:.4 .3 .2 .1 .1

代码在语义上与工作C ++代码相同, 然而 - 第一个条目没有排序,最后一个条目重复, 并且高位移动很少。 : - (

了解我们如何得到C ++日志:J = 3,i = 1&gt;破

并且在swift log中它变为:J = 3,i = 1 .. i = 0&gt;破

让我认为问题在于,当在IF条件下进行比较时,swift是如何展开通过引用传递的数组值。

一小时的研究表明:

| By default, array parameters are immutable 
| within the called function. To modify the copy 
| of the array that is passed to insertionSort, add
| var before toSort in the function header (Swift 1.2)

这种变化是Swift 3:
    |在Swift 3中,返回类型为inout [DONE]

所以我的问题是swift展开中的错误:move [i] .capturedPiece! 在做的时候:IF(移动![i]&gt; = tempMove){break} ??

我无法看到通过swift获得相同功能的方法,可以在C ++中实现

任何人都有任何关于在SWIFT 3中通过引用传递的数组进行插入排序的建议!?!?

约翰·彭纳(多伦多岛)

1 个答案:

答案 0 :(得分:1)

该问题与通过引用,值类型传递数组无关 或解开。真正的问题是在Swift中,

for i in stride(from:j-1, through:0, by:-1) { ... }

语句定义了一个仅在循环范围内有效的变量,可能隐藏了外部作用域中具有相同名称的变量。 你不能参考&#34;最后一个值&#34;之后的变量 循环语句(你可以在C中)。

在你的情况下,

i

为循环体的范围定义变量i,隐藏在函数顶部定义的外部变量theMoves[i+1] = tempMove 。因此在

i

var i : Int = 0 // variable 'i' was never mutated; consider changing to 'let' constant var j : Int = 0 // warning: initialization of variable 'j' was never used; consider replacing with assignment to '_' or removing it 始终为零,因为该变量从未更改过。

实际上,编译器会警告您这个问题:

func sortMoves( theMoves: inout [moveRecord])
{
    for j in 1..<theMoves.count {
        let tempMove = theMoves[j]
        var i = j-1
        while i >= 0 && abs(theMoves[i].capturedPiece!) < abs(tempMove.capturedPiece!) {
            theMoves[i+1] = theMoves[i]
            i -= 1
        }
        theMoves[i+1] = tempMove
    }
}

稍微简化的代码的正确版本将是

enumerate()