2016-07-22 4 views
4

私はこのコードをXcodeプレイグラウンドで試していましたが、descriptionゲッターメソッドがあまりにも多く呼ばれたことに気付きました。Swift:この場合、CustomStringConvertibleの説明が何回も実行されるのはなぜですか?

コードはここにある:両方print線でhttps://gist.github.com/T-Pham/4b72d17851162a32b2fc534f0618135d

はまず、コードが3176回実行されます。

enter image description here

コメントアウト最初printに続いて、コードが3164回実行されます。最初printコードを12回実行する必要があります意味

enter image description here

。しかし 、

enter image description here

ではなく148倍です。

答えて

4

これはあなたの頭を乱している遊び場です。

Playgroundは、CustomStringConvertibeプロトコルを持つ変数に対して独自の呼び出しをカウントしています(おそらく右側のパネルに情報を入力する)。

ミラーリング(ツリー)を全く印刷せずに呼び出すだけでこれが実現します。

あなたがあなた自身のカウンタを使用して呼び出しの実際の数をカウントした場合、それは非常に異なった結果得られます:ところで

var descCount = 0 
extension Node: CustomStringConvertible { 
    var description: String 
    { 
     descCount += 1 
     return "id: \(id)\nleft: \(left)\nright: \(right)" 
    } 
} 

descCount = 0 
print(tree) 
descCount // 12 

descCount = 0 
print(mirror(tree)) 
descCount // 12 

を、私は鏡()関数を理解少し問題があったと私は考え出し再帰的なものはおそらく理解するのが簡単だろう。どのノードにミラー()関数の追加について:

func mirror() -> Node 
{ 
    let result = Node() 
    result.id  = id 
    result.left = right?.mirror() 
    result.right = left?.mirror() 
    return result 
} 

print(tree.mirror()) 

[EDIT]ここでやや明確な構造を持つ非再帰ミラー機能(あなたと同じロジックが)です:

func mirror2(tree:Node) -> Node 
{ 
    // will return top of mirrored tree 
    let newTree = Node() 

    // node pair used for traversal and duplication 
    var original:Node! = tree 
    var mirrored:Node! = newTree 

    // traversal of tree structure left side first 
    // (uses mirrored tree to keep track of traversed nodes) 
    while original != nil 
    { 
     // carry node identifier (and contents eventually) 
     mirrored.id = original.id 

     // downwards, mirror left side first (if not already done) 
     if (original.left == nil) != (mirrored.right == nil) 
     { 
      original  = original.left 
      mirrored.right = Node() 
      mirrored  = mirrored.right 
      continue  
     } 

     // downwards, mirror right side second (if not already done) 
     if (original.right == nil) != (mirrored.left == nil) 
     { 
      original  = original.right 
      mirrored.left = Node() 
      mirrored  = mirrored.left 
      continue 
     } 

     // upwards from leaves and completed branches 
     original = original.parent 
     mirrored = mirrored.parent 
    } 
    return newTree 
} 

といくつかの視覚木の説明のためのお菓子:結果の比較を容易に結果

extension Node: CustomStringConvertible 
{ 
    var indent:String 
    { return " " + (parent?.indent ?? "") } 
    var description: String 
    { 
     return "\(id)\n" 
       + (left != nil ? "\(indent)L:\(left!)" : "") 
       + (right != nil ? "\(indent)R:\(right!)" : "") 
    } 
} 

print(tree) 

// 0 
// L:1 
//  L:3 
//  L:7 
//  R:8 
//  R:4 
//  L:9 
//  R:10 
// R:2 
//  R:6 
//  L:13 
//  R:14 
// 

print(mirror2(tree)) 

// 0 
// L:2 
//  L:6 
//  L:14 
//  R:13 
// R:1 
//  L:4 
//  L:10 
//  R:9 
//  R:3 
//  L:8 
//  R:7 
+0

ありがとう@Alain T ..ミラー関数について、要点は再帰を使用せずに実装することです –

関連する問題