Rotations d'arbres binaires


16

Les arbres de recherche binaires équilibrés sont essentiels pour garantir les recherches O (log n) (ou opérations similaires). Dans un environnement dynamique où de nombreuses clés sont insérées et / ou supprimées au hasard, les arbres peuvent dégénérer en listes liées qui sont horribles pour les recherches. Il existe donc différents types d' arbres binaires à équilibrage automatique qui neutralisent cet effet (tels que les arbres AVL ou les arbres évasés ). Ces arbres sont basés sur différents types de rotations qui rééquilibrent l'arbre.

Rotations

Dans ce défi, nous ne regarderons que les rotations à droite simples, une telle rotation (la rotation à gauche serait symétrique) ressemble à ceci:

    5            3
   / \          / \
  3   6   =>   1   5
 / \              / \
1   4            4   6

Si l'une des feuilles 1, 4ou 6avait des sous-arbres gauche ou droit, une rotation les garderait simplement là. S'il s'agit d'un sous-arbre d'un arbre plus grand, nous devons simplement le «couper» au nœud 5et «rattacher» l'arbre pivoté (maintenant le nœud 3) à ce nœud.

Défi

Étant donné un arbre de recherche binaire 1 et une clé, tournez à droite l'arbre sur ce nœud comme décrit ci-dessus. La clé fournie dans l'exemple ci-dessus serait 5.

Règles et E / S

  • vous pouvez utiliser n'importe quel type de clé tant qu'il y a une bijection entre les clés de votre choix et celles des cas de test
  • vous pouvez choisir n'importe quelle représentation pour les arbres binaires tant qu'il n'y a pas d'ambiguïté (par exemple, [3,[]]est ambigu sauf indication contraire) et c'est naturel pour la langue de votre choix
  • comme l'entrée sera toujours un arbre de recherche binaire, il n'y a pas de clés en double
  • vous pouvez supposer que la clé est contenue dans l'arborescence
  • vous pouvez supposer que le nœud contenant la clé a un enfant gauche
  • vous ne pouvez pas supposer un sous-arbre droit sous la clé fournie
  • vous ne pouvez pas supposer que l'arbre est déséquilibré avant la rotation
  • vous ne pouvez pas supposer que l'arbre est équilibré après la rotation
  • vous pouvez utiliser n'importe quelle méthode d'E / S par défaut
  • votre soumission peut être une fonction renvoyant l'arborescence ou un programme complet imprimant la solution

Cas de test

Ces exemples représentent un arbre comme suit

  • si c'est une feuille: []
  • si c'est un arbre avec clé xet que les deux sous-arbres sont des feuilles:[x]
  • si c'est un arbre avec clé xet sous-arbres left right:[x,left,right]

Le premier exemple est celui fourni dans la section Rotations . Si pour une raison quelconque , vous avez besoin d' une représentation graphique d'entre eux, ici 2 vous allez.

5 [5,[3,[1],[4]],[6]]  ->  [3,[1],[5,[4],[6]]]
5 [5,[3,[1],[4]],[]]  ->  [3,[1],[5,[4],[]]]
5 [5,[3,[],[4]],[6]]  ->  [3,[],[5,[4],[6]]]
5 [5,[3,[1],[]],[]]  ->  [3,[1],[5]]
4 [8,[4,[2,[1],[3]],[6,[5],[7]]],[12,[10,[9],[11]],[14,[13],[15]]]]  ->  [8,[2,[1],[4,[3],[6,[5],[7]]]],[12,[10,[9],[11]],[14,[13],[15]]]]
8 [10,[8,[6,[4,[2,[],[3]],[5]],[7]],[9]],[11]]  ->  [10,[6,[4,[2,[],[3]],[5]],[8,[7],[9]]],[11]]
10 [10,[8,[6,[4,[2,[],[3]],[5]],[7]],[9]],[11]]  ->  [8,[6,[4,[2,[],[3]],[5]],[7]],[10,[9],[11]]]
9 [6,[3,[2],[5]],[9,[8],[12,[11],[15,[14],[]]]]]  ->  [6,[3,[2],[5]],[8,[],[9,[],[12,[11],[15,[14],[]]]]]]
7 [7,[5,[3,[1],[4]],[6]],[8]]  ->  [5,[3,[1],[4]],[7,[6],[8]]]
15 [17,[9,[5,[2,[0],[4]],[8]],[15,[13,[11,[10],[12]],[14]],[16]]],[40,[27,[21,[19,[18],[20]],[24,[22],[25]]],[28]],[44,[42,[41],[]],[51,[47],[59,[55],[61]]]]]]  ->  [17,[9,[5,[2,[0],[4]],[8]],[13,[11,[10],[12]],[15,[14],[16]]]],[40,[27,[21,[19,[18],[20]],[24,[22],[25]]],[28]],[44,[42,[41],[]],[51,[47],[59,[55],[61]]]]]]
21 [17,[9,[5,[2,[0],[4]],[8]],[15,[13,[11,[10],[12]],[14]],[16]]],[40,[27,[21,[19,[18],[20]],[24,[22],[25]]],[28]],[44,[42,[41],[]],[51,[47],[59,[55],[61]]]]]]  ->  [17,[9,[5,[2,[0],[4]],[8]],[15,[13,[11,[10],[12]],[14]],[16]]],[40,[27,[19,[18],[21,[20],[24,[22],[25]]]],[28]],[44,[42,[41],[]],[51,[47],[59,[55],[61]]]]]]

1: ce qui signifie que pour tout noeud, toutes les clés du sous-arbre gauche seront plus petites que cette clé et toutes les clés du sous-arbre droit seront plus grandes que

2: pour éviter la pourriture des liens, je les ai intégrés en tant que commentaire

Réponses:


8

Haskell , 93 92 84 83 82 octets

data B=B[B]Int|L
k!B[l@(B[x,y]a),r]n|k<n=B[k!l,r]n|k>n=B[l,k!r]n|1>0=B[x,B[y,r]k]a

Merci à @BMO, @alephalpha et @Laikoni pour un octet chacun et @nimi pour huit octets!

Essayez-le en ligne!


L'utilisation data B=B[B]Intpermettrait d'économiser quelques octets supplémentaires.
Laikoni

@Laikoni juste un octet, je pense, mais je vais le prendre
Angs

Vous pouvez économiser 2 octets en fusionnant d'abord les deux cas, k<n=B[k!l,r]npuis k>n=B[l,k!r]nen un seul k/=n=B[k!l,k!r]n:, puis en ajoutant k!x=xpour rendre la correspondance de modèle exhaustive.
Radek

5

Vim , 25 octets

Prend l'entrée dans la clé et l'arborescence séparées par un espace. L'arbre devrait être représenté comme suit:

  • feuille: []
  • nœud avec clé k, enfant gauche <left>et enfant droit <right>:[ k <left><right>]

Pas les espaces autour de la clé kqui sont importants, tels que la solution fonctionne pour les arbres arbitraires.

"adw/ <C-r>a⏎3dw%l"apr[%xl%i]

Essayez-le en ligne!

Explication

"adw                           " delete the key and trailing space, keep in register a
    / <C-r>a⏎                  " move cursor to the key surrounded with spaces
             3dw               " remove key and [ (move left node to top)
                %l             " move cursor to the right subtree
                  "ap          " insert key there
                     r[        " insert a [ (appending subtree to key)
                       %       " move to the end of new left subtree
                        x      " remove ] (fix parentheses)
                         l%    " move to the end of new right subtree
                           i]  " insert ] (fix parentheses)

Aperçu

Voici un aperçu du premier scénario de test, généré avec ce script par Lynn :

                       Aperçu de Vim


3

Wolfram Language (Mathematica) , 30 octets

#2/.a_~b_~c_~#~d_:>b[a,c~#~d]&

Essayez-le en ligne!

Un arbre représenté comme suit:

  • si c'est une feuille: $ (vous pouvez la remplacer par n'importe quelle valeur qui n'est pas une clé)
  • si c'est un arbre avec clé xet sous-arbres left right:x[left,right]

Par exemple, l'arborescence du premier scénario de test est représentée par 5[3[1[$,$],4[$,$]],6[$,$]] .

Explication:

#2                                the second input
  /.                              replace
    a_~b_~c_~#~d_                 #[b[a,c],d], where # is the first input
                 :>               by
                   b[a,c~#~d]     b[a,#[c,d]]
                             &    define a function

3

Lisp commun, 146 octets

(defun r(k a)(cond((not a)a)((=(car a)k)`(,(caadr a),(cadadr a)(,(car a),(car(cddadr a)),(caddr a))))(t`(,(car a),(r k(cadr a)),(r k(caddr a))))))

Essayez-le en ligne ou vérifiez tous les tests!

Un arbre est représenté comme suit:

  • un arbre vide est représenté comme nil(ou de manière équivalente en Common Lisp comme la liste vide ())
  • un arbre non vide est représenté comme une liste de trois éléments (node left-subtree right-subtree) (donc une feuille Lest représentée comme (L nil nil)).

2

JavaScript (Node.js) , 70 octets

n=>f=a=>n-a[0]?(a[i=n<a[0]?1:2]=f(a[i]),a):(i=a[1],a[1]=i[2],i[2]=a,i)

Essayez-le en ligne! Le lien inclut des cas de test. Tous les nœuds doivent avoir des entrées gauche et droite mais ils peuvent []indiquer aucun sous-arbre de ce côté. Comme abréviation, la suite de tests utilise l(N)pour indiquer qu'il Ns'agit d'une feuille et l(N,L)pour indiquer qu'elle Na un sous-arbre gauche Lmais pas de sous-arbre droit à la fois en entrée et en sortie.



1

Gelée , 24 octets

ñ
Ḣ,1ịṪƊṭ@ṪṭḢð{Ḣ;ç€ɗ¹¡i?

Essayez-le en ligne!

Avertissement: Normalement, la ligne supérieure ne devrait pas exister et la ligne inférieure devrait avoir un ß, pas un ç. Cependant, des astuces de chaîne intelligentes etß ne vont pas bien ensemble, en raison deßarité variable de. Techniquement, j'aurais pu encore omettre la ligne supérieure, mais le résultat aurait dû être un programme complet, car sinon il devrait pouvoir être incorporé comme sa propre ligne dans n'importe quel programme, ce qui n'est possible que si vous suis chanceux. Cela signifie que, malheureusement, la sortie aurait eu une représentation ambiguë, car, lorsque vous soumettez un programme complet, ce qui obtient réellement la sortie compte, et non ce que le résultat est techniquement avant la fermeture du programme. Donc, afin de ne pas gâcher à la fois la récursivité et la représentation correcte des chaînes, j'ai décidé de soumettre une fonction à 2 lignes, où le travail de la ligne supérieure consiste simplement à appeler la fonction inférieure. La conséquence? Un énorme gaspillage de 2 octets précieux et précieux. Dans la défense de Jelly (et Dennis, ainsi que de tous les autres contributeurs),

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.