web-dev-qa-db-fra.com

Équilibrer un BST

Référence: On m'a posé cette question @MS SDE interview, 3rd round. Et ce n'est pas un problème de devoirs. J'ai également réfléchi et mentionné mon approche ci-dessous.

Question: Modifiez un BST afin qu'il devienne aussi équilibré que possible. Inutile de le mentionner, vous devez le faire le plus efficacement possible.

Indice: L'enquêteur a dit que c'était une question logique, si vous pensez différemment, vous obtiendrez la réponse. Aucun codage difficile n'est impliqué.
-> Cela dit, je ne pense pas qu'il s'attendait à ce que je pointe AVL/RB Trees.

Ma solution: J'ai proposé que, je ferais une traversée ordonnée de l'arbre, prendre l'élément central comme racine du nouvel arbre (appelons-le nouvelle racine). Ensuite, allez à la partie gauche de l'élément central, prenez son élément central comme racine du sous-arbre gauche de la nouvelle racine enracinée. Faites de même pour la partie droite. Faire cela récursivement donnera la BST équilibrée optimale.

Pourquoi je le poste ici: Mais il n'était pas satisfait de la réponse :( Donc, y a-t-il vraiment un moyen de le faire sans aller poids/stratégie de coloration RB, ou était-il juste en train de s'amuser avec moi?.

Dupliquer? Non ! Je sais qu'il y a ceci question mais la solution proposée par le demandeur est trop compliquée, et l'autre parle d'arbres AVL.

41
ADJ

Vous voudrez peut-être examiner l'algorithme Day-Stout-Warren, qui est un temps O (n), O (1) -Algorithme d'espace pour remodeler un arbre de recherche binaire arbitraire en un arbre binaire complet. Intuitivement, l'algorithme fonctionne comme suit:

  1. À l'aide de rotations d'arbre, convertissez l'arbre en une liste chaînée dégénérée.
  2. En appliquant des rotations sélectives à la liste liée, reconvertissez la liste en un arbre complètement équilibré.

La beauté de cet algorithme est qu'il s'exécute en temps linéaire et ne nécessite qu'une surcharge de mémoire constante; en fait, il remodèle simplement l'arbre sous-jacent, plutôt que de créer un nouvel arbre et de copier les anciennes données. Il est également relativement simple de coder.

J'espère que cela t'aides!

39
templatetypedef

"Équilibré autant que possible" = arbre binaire complet (ou complet)1. Vous ne pouvez pas être plus équilibré que cela.

La solution est simple - construire un arbre binaire complet "vide", et itérer le nouvel arbre et l'arbre d'entrée (simultanément) dans inorder-traversal pour remplir l'arbre complet.

Lorsque vous avez terminé, vous disposez de l'arborescence la plus équilibrée possible, et la complexité temporelle de cette approche est O(n).


MODIFIER:
Cela doit être fait en suivant ces étapes:

  1. Créez un arbre complet factice avec des nœuds n. Toutes les valeurs de chaque nœud seront initialisées à une valeur de poubelle.
  2. Créez deux itérateurs: (1) originalIter pour l'arborescence d'origine, (2) newIter pour la nouvelle arborescence (initialisée avec des ordures). Les deux itérateurs renverront les éléments dans une traversée dans l'ordre.
  3. Procédez comme suit pour remplir l'arborescence avec les valeurs de l'original:

     while (originalIter.hasNext()):
          newIter.next().value = originalIter.next().value
    

(1) (De Wikipedia): Un arbre binaire complet est un arbre binaire dans lequel chaque niveau, sauf éventuellement le dernier, est complètement rempli, et tous les nœuds sont aussi loin que possible à gauche

15
amit

L'algorithme DSW peut résoudre ceci est O(n) temps. L'algorithme se présente comme suit:

1] Using right-rotation operations, turn the tree into a linked list
   (a.k.a. backbone or Vine)
2] Rotate every second node of the backbone about its parent to turn
   the backbone into a perfectly balanced BST. 

Référence

11
thunderbird