Sortare cu un arbore binar

Sortarea folosind un arbore binar (sortare arbore binar, sortare arbore, sortare arbore, sortare folosind un arbore binar, ing.  sortare arbore ) este un algoritm de sortare universal care constă în construirea unui arbore binar de căutare prin cheile unui tablou (listă), urmată de asamblarea tabloului rezultat prin parcurgerea nodurilor arborelui construit în ordinea necesară a cheilor. Această sortare este optimă atunci când se primesc date prin citire directă dintr -un flux (de exemplu, un fișier, socket sau consolă).

Algoritm

  1. Construcția unui arbore binar.
  2. Asamblarea tabloului rezultat prin parcurgerea nodurilor în ordinea cerută a tastelor.

Eficiență

Procedura de adăugare a unui obiect la un arbore binar are o complexitate algoritmică medie de ordinul . În consecință, pentru n obiecte, complexitatea va fi , care clasifică sortarea folosind un arbore binar ca un grup de „sortări rapide”. Cu toate acestea, complexitatea adăugării unui obiect la un arbore dezechilibrat poate fi la fel de mare ca , ceea ce poate duce la o complexitate generală de ordinul .

Când se extinde fizic o structură arborescentă în memorie, sunt necesare cel puțin celule de memorie suplimentare (fiecare nod trebuie să conțină referințe la un element al matricei originale, la elementul părinte, la frunza din stânga și din dreapta), cu toate acestea, există modalități de a reduce memoria suplimentară necesară.

Exemple de implementare

Într-o formă simplă de programare funcțională în Haskell , acest algoritm ar arăta astfel:

Arborele de date a = Frunza | Nodul ( Arborele a ) a ( Arborele a ) insert :: Ord a => a -> Tree a -> Tree a insert x Leaf = Node Leaf x Leaf insert x ( Nod t y t' ) | x <= y = Nod ( insert x t ) y t' insert x ( Node t y t' ) | x > y = Nodul t y ( inserați x t' ) aplatiza :: Arborele a -> [ a ] ​​​​aplatiza Frunza = [] aplatiza ( Nodul t x t' ) = aplatiza t ++ [ x ] ++ aplatiza t' treesort :: Ord a => [ a ] ​​​​-> [ a ] ​​​​treesort = aplatiza . foldr insert Leaf


Implementare în C++14 :

#include <memorie> #include <cassert> #include <algoritm> #include <vector> #include <iostream> folosind namespace std ; // clasă reprezentând o clasă de arbore binar BinaryTree { protejat : // structura nodului arborelui binar BinaryTreeNode { shared_ptr < BinaryTreeNode > stânga , dreapta ; // tasta int subarboresc stânga și dreapta ; // tasta }; shared_ptr < BinaryTreeNode > m_root ; // rădăcina copacului protejată : // procedura recursivă de inserare a cheii // cur_node - nodul curent al arborelui cu care este comparat nodul inserat // node_to_insert - nodul inserat void insert_recursive ( const shared_ptr < BinaryTreeNode >& cur_node , const shared_ptr < BinaryTreeNode >& insert node ) _to_ { assert ( cur_node != nullptr ); // compara bool insertIsLess = node_to_insert -> cheie < cur_node -> cheie ; if ( insertIsLess ) { // se inserează în subarborele din stânga dacă ( cur_node -> stânga == nullptr ) cur_node -> stânga = nod_to_insert ; altfel insert_recursive ( cur_node -> stânga , nod_to_insert ); } altfel { // se inserează în subarborele din dreapta dacă ( cur_node -> dreapta == nullptr ) cur_node -> dreapta = nod_to_insert ; altfel insert_recursive ( cur_node -> dreapta , nod_to_insert ); } } public : void insert ( tasta int ) { shared_ptr < BinaryTreeNode > node_to_insert ( nou BinaryTreeNode ); nod_to_insert -> cheie = cheie ; if ( m_root == nullptr ) { m_root = nod_la_inserare ; întoarcere ; } insert_recursive ( m_root , node_to_insert ); } public : typedef function < void ( tasta int ) > Vizitator ; protejat : // procedura de traversare a arborelui recursiv // cur_node - nodul vizitat în prezent void visit_recursive ( const shared_ptr < BinaryTreeNode >& cur_node , const Visitor & visitor ) { assert ( cur_node != nullptr ); // vizitați mai întâi subarborele din stânga dacă ( cur_node -> stânga != nullptr ) visit_recursive ( cur_node -> stânga , vizitator ); // vizitează elementul vizitator curent ( cur_node -> cheie ); // vizitați subarborele din dreapta dacă ( cur_node -> dreapta != nullptr ) visit_recursive ( cur_node -> dreapta , vizitator ); } public : void visit ( const Vizitator & vizitator ) { if ( m_root == nullptr ) întoarcere ; visit_recursive ( m_root , vizitator ); } }; int main () { BinaryTree ; _ // adăugarea elementelor la vectorul arborelui < int > data_to_sort = { 10 , 2 , 7 , 3 , 14 , 7 , 32 }; pentru ( valoare int : date_to_sort ) { copac . inserare ( valoare ); } // tree traversal tree . vizitează ([]( int cheie_vizitata ) { cout << cheie_vizitata << " " ; }); cout << endl ; // rezultatul executiei: 2 3 7 7 10 14 32 return 0 ; }


Un exemplu de creare a unui arbore binar și sortare în Java :

// Compilați și tastați java TreeSort class Tree { public Tree left ; // subarborele stânga și dreapta și cheia public Tree right ; cheie publică ; _ public Tree ( int k ) { // constructor cu cheie de inițializare a cheii = k ; } /* insert (adăugarea unui nou subarbore (cheie)) compară cheia subarborelui de adăugat (K) cu cheia nodului rădăcină (X). Dacă K>=X, adăugați recursiv un nou arbore la subarborele din dreapta. Dacă K<X, adăugați recursiv un nou arbore în subarborele din stânga. Dacă nu există un subarboresc, atunci introduceți un nou arbore în acest loc */ public void insert ( Arborele aArborele ) { if ( Arborele . cheia < cheia ) if ( stânga != nul ) stânga . inserare ( aTree ); else left = aTree ; else if ( right != null ) right . inserare ( aTree ); else right = aTree ; } /* traversează Parcurge recursiv subarborele din stânga. Aplicați funcția f (print) la nodul rădăcină. Traversați recursiv subarborele din dreapta. */ public void traverse ( TreeVisitor vizitator ) { if ( left != null ) left . traversează ( vizitator ); vizitator . vizita ( aceasta ); dacă ( corect != nul ) corect . traversează ( vizitator ); } } interfață TreeVisitor { public void visit ( Tree node ); }; clasa KeyPrinter implementează TreeVisitor { public void visit ( Tree node ) { System . afară . println ( " " + nod . cheie ); } }; class TreeSort { public static void main ( String args [] ) { Tree myTree ; myTree = Arborele nou ( 7 ); // creează un arbore (cu cheie) myTree . inserați ( Arbore nou ( 5 ) ); // atașați subarborele myTree . inserare ( Arbore nou ( 9 ) ); MyTree . traversează ( nouă KeyPrinter ()); } }


Vezi și