2013-05-07 225 views
1

如果我想按順序打印所有音高,那麼左側先出現然後右側出現,我如何重複以下內容。對於下面的第一段代碼;答案應該是a4,b4,c4,d4。我怎樣才能實現這個程序化?Javascript:遍歷二叉樹?

var melody2_mus = 
    { tag: 'seq', 
     left: 
     { tag: 'seq', 
     left: { tag: 'note', pitch: 'a4', dur: 250 }, 
     right: { tag: 'note', pitch: 'b4', dur: 250 } }, 
     right: 
     { tag: 'seq', 
     left: { tag: 'note', pitch: 'c4', dur: 500 }, 
     right: { tag: 'note', pitch: 'd4', dur: 500 } } } 

又如:

var melody2_mus = 
     { tag: 'seq', 
      left: { tag: 'note', pitch: 'b4', dur: 250 } }, 
      right: 
      { tag: 'seq', 
      left: { tag: 'note', pitch: 'c4', dur: 500 }, 
      right: { tag: 'note', pitch: 'd4', dur: 500 } } } 

應該打印B4,C4,D4

由於

+1

試圖按順序深度優先遍歷? http://en.wikipedia.org/wiki/Tree_traversal#In-order – 2013-05-07 15:47:34

回答

5

遞歸函數是最簡單的:

function traverse(obj) { 
    // always follow left branch first 
    if (obj.left) { 
     traverse(obj.left); 
    } 

    // do stuff for leaf nodes 
    if (obj.pitch) { 
     console.log(obj.pitch); 
    } 

    // then the right branch if it exists 
    if (obj.right) { 
     traverse(obj.right); 
    } 
} 

參見http://jsfiddle.net/alnitak/E2ZEB/

或者更一般地:

function traverse(obj, func) { 
    if (!obj) return; 

    traverse(obj.left, func); 
    func(obj); 
    traverse(obj.right, func); 
} 
+0

我甚至會期望一個節點*或者*是一個帶'pitch'的葉子*或*有'left'和'right'子元素。順便說一句,你的後序遍歷不是最直觀的:-) – Bergi 2013-05-07 15:53:54

+0

@Alnitak:啊,如果他只將數據存儲在葉節點中,那麼我相信你是對的。 – Matt 2013-05-07 15:55:16

+0

@感謝Alnitak,我的數據只存儲在葉節點中。 – user1788175 2013-05-07 15:59:31

1

這裏的參宿一的回答的一個副本,但與訪問者模式抽象。

function traverse(obj, cb) { 
    cb(obj); 
    if (obj.left) { 
     traverse(obj.left, cb); 
    } 
    if (obj.right) { 
     traverse(obj.right, cb); 
    } 
} 

var melody2_mus = 
    { tag: 'seq', 
     left: 
     { tag: 'seq', 
     left: { tag: 'note', pitch: 'a4', dur: 250 }, 
     right: { tag: 'note', pitch: 'b4', dur: 250 } }, 
     right: 
     { tag: 'seq', 
     left: { tag: 'note', pitch: 'c4', dur: 500 }, 
     right: { tag: 'note', pitch: 'd4', dur: 500 } } } 

traverse(melody2_mus, function(node) { 
    if (node.pitch) { 
     console.log(node.pitch); 
    } 
}); 

http://jsfiddle.net/E2ZEB/3/

+0

我敢肯定,在一般情況下,當一個節點也可能有一個值時,你需要調用'.left'和'.right'節點之間的'cb'。 – Alnitak 2013-05-07 17:44:58

+0

@Alnitak它取決於所需的遍歷類型,不是嗎?只需將它移動到正確的遍歷類型? – 2013-05-07 18:12:42

+0

當節點的值可能高於左節點的值(及其後代)並低於右節點的值時。但是,如果分支節點不能有值,順序無關緊要。 – Alnitak 2013-05-07 18:25:58