2010-12-08 77 views
0

Comment puis-je implémenter une fonction d'égalité dans Scheme qui prend 2 arbres et vérifie s'ils ont à la fois les mêmes éléments et la même structure?Fonction de vérification de l'égalité entre les arbres

+0

Pensez-y un peu. Si nous avons deux arbres, chacun avec un élément, comment pourrions-nous dire s'ils étaient égaux? –

+0

égalité de longueur (puisqu'ils sont représentés par des listes), ou avec "eq?" peut être? – pantelis4343

+0

Vous essayez toujours de passer directement à une solution pour l'ensemble. Ce n'est pas la bonne façon d'y parvenir - vous voulez résoudre le plus petit problème possible, puis construire une solution plus grande à partir de cela. Donc, si nous avons un arbre de * un élément * (il contient juste le nœud racine), et nous avons un autre arbre de * un élément *, comment vérifierions-nous s'ils étaient identiques? –

Répondre

3

récursion de la racine chacun des arbres
si les valeurs de racines sont semblables - continuer avec la sous-arborescence à gauche, puis sous-arbre droit
toute différence - break

1

Nous pourrions utiliser égaux?

(equal? '(a (b (c))) '(a (b (c)))) 

Mais, pour l'amusement, à la suite de la mention Vassermans d'une « rupture », cela pourrait être une bonne occasion de profiter de la poursuite des systèmes de contrôle de puissance!

Nous pouvons utiliser appel/cc pour émettre un retour anticipé si nous remarquons une différence dans les arbres. De cette façon, nous pouvons simplement revenir à la poursuite des appelants sans avoir à dérouler la pile.

Voici un exemple très simple. Il suppose que les arbres sont bien formés et ne contiennent que des symboles en guise de feuilles, mais il est souhaitable que le concept soit démontré. Vous verrez que la procédure accepte explicitement la continuation en tant que paramètre.

(define (same? a b return) 
    (cond 
    ((and (symbol? a) (symbol? b))  ; Both Symbols. Make sure they are the same. 
     (if (not (eq? a b)) 
     (return #f))) 
    ((and (empty? a) (empty? b)))  ; Both are empty, so far so good. 
    ((not (eq? (empty? a) (empty? b))) ; One tree is empty, must be different! 
     (return #f)) 
    (else 
     (begin 
     (same? (car a) (car b) return) ; Lets keep on looking. 
     (same? (cdr a) (cdr b) return))))) 

appel/cc nous permet de capturer la poursuite actuelle. Voici comment j'ai appelé cette procédure:

(call/cc (lambda (k) (same? '(a (b)) '(a (b)) k)))      ; --> #t 
(call/cc (lambda (k) (same? '(a (b (c) (d e))) '(a (b (c) (d e))) k))) ; --> #t 
(call/cc (lambda (k) (same? '(a (b (F) (d e))) '(a (b (c) (d e))) k))) ; --> #f 
(call/cc (lambda (k) (same? '(a (b)) '(a (b (c) (d))) k)))    ; --> #f 
+0

Qu'est-ce que 'call/cc' a à faire avec la question originale? Il semble que vous vouliez simplement utiliser CPS ici sans raison; ça ne change pas tellement le code. Cela dit, vous n'avez jamais '(return #t)' donc '# t' ne devrait jamais être retourné. – configurator

+0

Oui, c'était gratuit. Est-ce une mauvaise forme? Vous avez tort d'avoir à invoquer explicitement la continuation. Essayez-le ... –

+0

J'essaie de l'exécuter, mais dr-scheme se plaint des clauses else manquantes sur les ifs. Et #t doit apparaître à un moment donné, n'est-ce pas? Je vais essayer ma main à une recherche basée sur la continuation. –

0

J'ai aussi une réponse continue. Mais maintenant j'ai deux suites, une si elle est vraie, et une si elle est fausse. Ceci est utile si vous voulez ramifier le résultat. J'ai aussi inclus 'same ?, qui cache toutes les suites afin que vous n'ayez pas à les traiter.

(define (same? a b) 
    (call/cc (λ (k) (cont-same? a b (λ() (k #t)) (λ() (k #f)))))) 

(define (cont-same? a b return-t return-f) 
    (define (atest c d) 
    ;; Are they foo? If they both are, then true 
    ;; If they both aren't false 
    ;; if they are different, then we are done 
    (if (and c d) 
     #t 
     (if (or c d) 
      (return-f) 
      #f))) 

    (if (atest (null? a) (null? b)) ;; Are they both null, or both not null. 
     (return-t) 
     (if (atest (pair? a) (pair? b)) 
      (cont-same? (car a) 
         (car b) 
         (λ() (cont-same? (cdr a) (cdr b) ;; If the head are the same, compare the tails 
             return-t return-f)) ;; and if the tails are the same, then the entire thing is the same 
         return-f)   
      (if (equal? a b) ;; Both are atoms 
       (return-t) 
       (return-f))))) 
+0

thx tout pour votre aide. Je l'ai eu maintenant :) – pantelis4343

+0

@pantenlis Vous devriez vérifier une réponse comme correcte alors, de sorte que la question est fermée. –