2016-06-19 3 views
2

Ich schreibe Funktionen zum Serialisieren und Deserialisieren eines Binärbaums (nur Umwandlung in ein Array und zurück zu einem BT) und mir fällt es schwer, die schreiben Deserialisierungsfunktion, ohne eine globale Variable zu verwenden, um den Index zu verfolgen.Rekursive Funktion, verwalten Sie einen globalen Zähler ohne eine globale Variable

meine Node-Klasse sieht wie folgt aus:

class Node { 
    constructor(value) { 
    this.value = value 
    this.left = null 
    this.right = null 
    } 
} 

und meine serialize Methode sieht wie folgt aus:

function serialize(node = this, list = []) { 
    if (!node) { 
    list.push('#') 
    return 
    } 

    list.push(node.value) 
    serialize(node.left, list) 
    serialize(node.right, list) 
    return list 
} 

Hier ist mein Problem, in der deserialize Funktion muss ich für die eine globale Variable halten 'index', gibt es eine Möglichkeit, den globalen Wert für den Index zu behalten, ohne eine globale Variable zu erstellen?

let index = 0 

function deserialize(list) { 
    if (index === list.length || list[index] === '#') { 
    index++ 
    return 
    } 

    const tree = new Node(list[index]) 
    index++ 

    tree.left = deserialize(list) 
    tree.right = deserialize(list) 

    return tree 
} 

Ich schrieb zunächst die Funktion wie folgt aus: (aber ich hatte die Index-Variable auf eine globale Variable Refactoring)

function deserialize(list, index = 0) { 
    if (index === list.length || list[index] === '#') { 
    index++ 
    return 
    } 

    const tree = new Node(list[index]) 
    index++ 

    tree.left = deserialize(list, index) 
    tree.right = deserialize(list, index) 

    return tree 
} 

Diese endete mit einem symetric Baum, weil die tree.left und Baum .right würde immer den gleichen Index nehmen.

Ich bin nur neugierig, ob es eine einfache Möglichkeit gibt, den Index in einer rein rekursiven Funktion (ohne eine rekursive Subroutine) zu verfolgen, ohne eine globale Variable zu erstellen.

Antwort

3

Pass ein Stöckchen mit einem Mitglied können Sie aktualisieren, wie Sie Rekursion:

function deserialize(list, baton={index: 0}) { 
    var b = baton; // shorthand 
    if (b.index === list.length || list[b.index] === '#') { 
    b.index++; 
    return; 
    } 

    const tree = new Node(list[b.index]); 
    b.index++; 

    tree.left = deserialize(list, b); 
    tree.right = deserialize(list, b); 

    return tree; 
} 
4

Ein allgemeiner Weg, dies zu tun:

function wrapperFunction(args) { 
    var bookkeepingStuff = whatever; 
    function actualRecursiveFunction(args) { 
    // code 
    } 

    return actualRecursiveFunction(args); 
} 

einfach die reale rekursive Funktion in einer anderen Funktion wickeln. Alle lokalen Variablen des Wrappers werden effektiv wie globale Variablen für die reale rekursive Funktion sein, die darin verschachtelt ist.

+0

Oder die kürzere 'return function actualRecursiveFunction (args) {/ * code * /} (args);' – Oriol

+0

Danke, das funktioniert, aber meine Frage wurde gefragt, wie dies ohne eine rekursive Subroutine wie Sie in dieser Antwort tun – jmancherje

+1

@jmancherje der Overhead einer Wrapper-Funktion ist vernachlässigbar; Es gibt keinen Grund (kein * guter * Grund), dieses Muster nicht zu verwenden. Es ist eine sehr häufige Redewendung in der funktionalen Programmierung. – Pointy

Verwandte Themen