2013-05-07 2 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, с4, d4

Благодарности

+1

Пытался в заказе глубине первого обход? http://en.wikipedia.org/wiki/Tree_traversal#In-order –

ответ

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

Я бы даже ожидал, что узел * либо * будет листом с «шагом» * или * имеет как «левые», так и «правильные» дети. Кстати, ваш ход после заказа не самый интуитивный :-) – Bergi

+0

@Alnitak: Ах, если он хранит данные только в листовых узлах, то я считаю, что вы правы. – Matt

+0

@ Спасибо Alnitak, мои данные хранятся только в листовых узлах. – user1788175

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

Я уверен, что вам нужно называть 'cb' _between_ узлами' .left' и '.right' в общем случае, когда узел также может иметь значение. – Alnitak

+0

@Alnitak Это зависит от типа обхода, не так ли? Просто переместите его для правильного типа обхода? –

+0

, когда узел может иметь значение, он будет больше значения левого узла (и его потомков) и ниже значений правого узла. Однако порядок не имеет значения, если узлы ветвления не могут иметь значение. – Alnitak

Смежные вопросы