Algoritmul QuickSort în JavaScript cu exemplu

⚡ Rezumat inteligent

Algoritmul QuickSort în JavaScriptul sortează o matrice la locul ei prin alegerea unui pivot, partiționarea valorilor mai mici la stânga și a valorilor mai mari la dreapta, apoi prin recursivitate. Calculează media lui O(n log n) și depășește performanța sort() încorporată pe seturi de date numerice mari.

  • 🎯 Alegere pivot: Alegeți elementul din mijloc; un pivot al primului element degradează o matrice deja sortată la O(n²).
  • ✂️ partiție: Mută ​​indicatorul din stânga peste valorile mai mici, indicatorul din dreapta peste valorile mai mari, apoi inversează-le.
  • 🔁 Recursie: Apelați quickSort pe ambele părți ale indexului returnat până când fiecare subinterval conține câte un element.
  • ⚡ Complexitate: Cel mai bun și cel mediu timp este O(n log n), cel mai rău timp este O(n²), iar spațiul stivei este O(log n).
  • ⚠️ capcană sort(): Apelarea funcției sort() fără comparator compară valorile formate din șiruri de caractere, astfel încât [10,9,1] devine [1,10,9].
  • 🧩 Nu este stabil: Sortarea rapidă schimbă elementele distanțate, astfel încât cheile egale își pot schimba ordinea; sortarea prin îmbinare o păstrează.
  • 🛠️ Utilizare reală: Transmiteți o funcție de comparare pentru a sorta obiecte, șiruri de caractere sau date cu o logică de partiție identică.

Algoritmul QuickSort în JavaScenariu

Ce este sortarea rapidă?

Sortare rapida este un algoritm de sortare prin comparație care urmează Diviza și cuceri abordare. Selectează un element ca pivot, împarte matricea într-o parte care conține valori mai mici decât pivotul și o parte care conține valori mai mari, apoi aplică aceeași procedură fiecărei părți până când întreaga matrice este ordonată.

Sortarea rapidă este unul dintre cei mai utilizați algoritmi de sortare în fiecare limbaj de programare. Dacă scrieți JavaScenariu, probabil ați folosit deja funcția încorporată fel() metoda, așa că s-ar putea să vă întrebați de ce merită să învățați o implementare separată de sortare rapidă. Pentru a răspunde la această întrebare, trebuie mai întâi să știți ce înseamnă sortarea și care este sortarea implicită în JavaScriptul chiar o face.

Trei proprietăți definesc sortarea rapidă:

  • În loc: rearanjează originalul mulțime și nu alocă o a doua matrice de aceeași dimensiune.
  • Recursiv: fiecare partiție produce două intervale mai mici care sunt sortate după aceeași funcție.
  • Instabil: Două elemente cu chei egale pot ajunge într-o ordine relativă diferită față de cea în care au început.

Ce este Sortarea?

Sortarea înseamnă aranjarea elementelor într-o ordine definită. Aproape sigur ați întâlnit acest lucru la școală: aranjarea numerelor de la cel mai mic la cel mai mare este... ascendent ordine, iar așezarea lor de la cea mai mare la cea mai mică este Descendentă ordine. Sortarea nu se limitează la numere. Șirurile pot fi ordonate alfabetic, datele cronologic, iar obiectele după orice câmp ales, cum ar fi prețul sau scorul.

Sortarea este importantă deoarece datele ordonate permit operațiuni mai rapide. O căutare binară se execută în timp O(log n), dar numai pe date de intrare sortate. Operațiunile de deduplicare, interogările de interval, clasare și îmbinare devin mult mai ieftine odată ce datele sunt în ordine, motiv pentru care fiecare limbaj de programare include cel puțin o rutină de sortare.

Sortare implicită în JavaScenariu

Ca menționat mai devreme, JavaScriptul oferă fel()Luați o matrice mică, cum ar fi [5,3,7,6,2,9], pe care o doriți în ordine crescătoare. Apelarea fel() pe matrice pare să facă exact asta.

Sortare implicită JavaScenariu

Captura de ecran de mai sus arată consola browserului care afișează matricea sortată. Iată același cod:

var items = [5, 3, 7, 6, 2, 9];
console.log(items.sort());

ieșire:

[ 2, 3, 5, 6, 7, 9 ]

Rezultatul este corect, dar numai din întâmplare. Array.prototype.sort() convertește fiecare element într-un șir de caractere și compară șirurile de caractere cu excepția cazului în care furnizați o funcție de comparare. Fiecare valoare din această matrice este o singură cifră, deci ordinea șirurilor se întâmplă să corespundă cu ordinea numerică. Schimbați datele și iluzia se epuizează.

var prices = [10, 9, 1, 100, 25];
console.log(prices.sort());                              // string comparison
console.log(prices.sort(function (a, b) { return a - b; })); // numeric comparison

ieșire:

[ 1, 10, 100, 25, 9 ]
[ 1, 9, 10, 25, 100 ]

⚠️ Atenție: Nu suna niciodată sort() pe numere fără comparator. „100” se sortează înainte de „25” deoarece caracterul „1” se află înainte de caracterul „2”. Scrieți întotdeauna sort((a, b) => a - b) pentru date numerice.

Ce algoritm folosește sort()?

Specificația nu denumește un algoritm, așa că fiecare motor își alege propriul algoritm. Motoarele moderne folosesc toate un algoritm bazat pe îmbinare:

  • V8 (Chrome, Edge, Node.js) a folosit TimSort începând cu versiunea V8 7.0, disponibil în Chrome 70.
  • Maimuta paianjen (Firefox) utilizează fuzionează sort.
  • JavaScriptCore (Safari) folosește și fuzionează sort.

Începând cu ES2019, limba garantează că sort() is stabil, ceea ce exclude o sortare rapidă simplă în interiorul motorului. Sortarea bazată pe îmbinare necesită O(n) memorie auxiliară și trebuie să apeleze JavaComparator de scripturi pentru fiecare comparație. O funcție de sortare rapidă numerică scrisă de mână compară numerele direct și sortează pe loc, astfel încât poate fi eficientă pe tablouri numerice mari. Sortarea a 1,000,000 de numere întregi aleatorii pe Node.js 22 a durat aproximativ 100 ms cu Sortarea rapidă de mai jos și aproximativ 210 ms implementate cu sort((a, b) => a - b).

Așadar, merită să scrieți Quick Sort atunci când aveți nevoie de sortare in situ, control strict asupra memoriei sau pur și simplu o înțelegere solidă a modului în care funcționează sortarea. Să analizăm mecanismele în detaliu.

Cum funcționează sortarea rapidă?

Sortarea rapidă repetă o operație principală, numită partiționare, pe intervale din ce în ce mai mici. Iată pașii în ordine:

  1. Găsi pivot element din matrice.
  2. Începeți indicatorul din stânga la primul element al intervalului.
  3. Începeți indicatorul din dreapta la ultimul element al intervalului.
  4. Comparați elementul de la indicatorul din stânga cu pivotul. Dacă este mai mic decât pivotul, mutați indicatorul din stânga cu un pas spre dreapta. Continuați până când elementul din stânga este mai mare sau egal cu pivotul.
  5. Comparați elementul de la indicatorul din dreapta cu pivotul. Dacă este mai mare decât pivotul, mutați indicatorul din dreapta cu un pas spre stânga. Continuați până când elementul din dreapta este mai mic sau egal cu pivotul.
  6. Dacă indicatorul din stânga este în continuare mai mic sau egal cu indicatorul din dreapta, inversați cele două elemente.
  7. Crește indicatorul din stânga și decrementează indicatorul din dreapta.
  8. Dacă indicele din stânga este încă mai mic sau egal cu indicele din dreapta, repetați de la pasul 4. În caz contrar, returnați indicele indicatorului din stânga.

Cum funcționează QuickSort

Diagrama de mai sus tracacele mișcări ale indicatorului pe o matrice eșantion. Fiecare element mai mic decât pivotul se termină în stânga sa, iar fiecare element mai mare se termină în dreapta sa, exact ceea ce marchează indexul returnat. Secțiunea de mai jos prezintă pas cu pas aceeași matrice.

Cum se determină elementul pivot

Alegerea pivotului este singura decizie care diferențiază o sortare rapidă de una lentă. Dacă luați întotdeauna în considerare primul element, o matrice deja sortată produce cea mai proastă divizare posibilă: o parte goală și o parte cu fiecare element rămas. Aceasta transformă algoritmul în O(n²). Luând de mijloc elementul (lungimea matricei împărțită la doi) evită această capcană pentru intrările sortate și sortate invers, motiv pentru care codul de mai jos îl folosește.

Strategii comune de pivotare:

  • Primul sau ultimul element: cel mai simplu de codat, dar O(n²) pe date sortate.
  • Elementul din mijloc: o valoare implicită bună care gestionează tablouri sortate și sortate invers în O(n log n).
  • Element aleatoriu: face imposibilă construirea în avans a datelor de intrare pentru cel mai defavorabil caz.
  • Mediana a trei: ia mediana primei, celei din mijloc și celei de-a doua valori; alegerea standard în bibliotecile de producție.

Acum parcurgeți sortarea rapidă pe matrice [5,3,7,6,2,9].

PASUL 1: Pivotul este elementul din mijloc. Cu stânga = 0 și dreapta = 5, Math.floor((5 + 0) / 2) dă indicele 2, deci valoarea pivot este 7.

PASUL 2: Indicatorii încep la capetele tabloului. Indicatorul din stânga este la indexul 0 (valoare 5) și indicatorul din dreapta este la indicele 5 (valoare 9).

PASUL 3: Comparați valoarea din stânga cu pivotul. 5 < 7, deci mutați la dreapta la indicele 1. 3 < 7, deci mutați la dreapta la indicele 2. Valoarea de acolo este 7, care nu este mai mică decât pivotul, deci indicatorul din stânga se oprește la indicele 2.

PASUL 4: Comparați valoarea din dreapta cu pivotul. 9 > 7, deci mutați la stânga la indicele 4. Valoarea de acolo este 2, care nu este mai mare decât pivotul, deci indicatorul din dreapta se oprește la indicele 4.

PASUL 5: Indicele din stânga (2) este mai mic sau egal cu indicele din dreapta (4), deci inversați cele două valori. Tabloul devine [5,3,2,6,7,9].

PASUL 6: Mutați ambele indicatoare cu un pas spre interior. Indicatorul din stânga se află acum la indicele 3, iar indicatorul din dreapta la indicele 3.

PASUL 7: Repetați scanarea. Valoarea de la indicele 3 este 6, iar 6 < 7, deci indicatorul din stânga avansează la indicele 4. Valoarea de la indicele 3 nu este mai mare decât pivotul, deci indicatorul din dreapta rămâne la indicele 3.

PASUL 8: Indicele din stânga (4) este acum mai mare decât indicele din dreapta (3), deci bucla se termină și funcția returnează 4Tot ce se află înainte de indicele 4 este mai mic sau egal cu pivotul, iar tot ce se află de la indicele 4 încolo este mai mare sau egal cu acesta.

Pe baza acestei soluții, aveți nevoie de cod pentru două operații: swapping două elemente și partiționarea unui interval.

Code a schimba două Numbers in JavaScenariu

schimbă două numere JavaScenariu

După cum se arată în captura de ecran a editorului de mai sus, ajutorul pentru swap folosește o variabilă temporară pentru a schimba valorile la doi indecși. Mută ​​direct matricea și nu returnează nimic.

function swap(items, leftIndex, rightIndex) {
    var temp = items[leftIndex];
    items[leftIndex] = items[rightIndex];
    items[rightIndex] = temp;
}

var demo = [5, 3, 7, 6, 2, 9];
swap(demo, 0, 5);
console.log(demo);

ieșire:

[ 9, 3, 7, 6, 2, 5 ]

💡 Sfat: Modern JavaScriptul poate schimba date fără o variabilă temporară folosind destructurarea array-ului: [items[i], items[j]] = [items[j], items[i]];Se citește mai clar, deși ajutorul explicit este puțin mai rapid în buclele active, deoarece evită alocarea unui array temporar.

Code pentru a efectua partiționarea

Code pentru a efectua partiția

Codul din captura de ecran de mai sus transformă pașii 1-8 într-o funcție. Cele două funcții interne bucle avansați indicatoarele, if Blocul efectuează schimbarea, iar funcția returnează indexul de divizare.

function partition(items, left, right) {
    var pivot   = items[Math.floor((right + left) / 2)], // middle element
        i       = left,  // left pointer
        j       = right; // right pointer
    while (i <= j) {
        while (items[i] < pivot) {
            i++;
        }
        while (items[j] > pivot) {
            j--;
        }
        if (i <= j) {
            swap(items, i, j); // swap two elements
            i++;
            j--;
        }
    }
    return i;
}

var items = [5, 3, 7, 6, 2, 9];
var index = partition(items, 0, items.length - 1);
console.log(items);
console.log(index);

ieșire:

[ 5, 3, 2, 6, 7, 9 ]
4

Rezultatul corespunde exact cu ghidul manual: după o singură trecere prin partiție, matricea este [5,3,2,6,7,9], iar indexul de divizare returnat este 4.

Efectuați recursivul OperaTION

Odată ce partiționarea returnează indexul de divizare, acesta se folosește pentru a împărți intervalul și a rula sortarea rapidă pe fiecare jumătate. De aceea se numește algoritmul „Împarte și Constrânge”. Recursivitatea continuă până când fiecare subinterval conține un singur element, moment în care întreaga matrice este sortată.

Notă: Sortarea rapidă funcționează pe aceeași matrice pe tot parcursul procesului. Nu se creează matrice noi în acest proces, ceea ce îl face un algoritm in-site.

Deci, îl suni pe partiție () funcția explicată mai sus și folosiți valoarea sa returnată pentru a diviza mulțime în părți. Iată codul care face acest lucru:

recursive OperaTION

Observați cele două condiții de protecție evidențiate în captură de ecran. left < index - 1 confirmă că cel puțin două elemente rămân în partea stângă și index < right confirmă același lucru și pentru partea dreaptă. Fără aceste gărzi, funcția s-ar apela singură la nesfârșit pe intervalele cu un singur element.

function quickSort(items, left, right) {
    var index;
    if (items.length > 1) {
        index = partition(items, left, right); // index returned from partition
        if (left < index - 1) { // more elements on the left side of the pivot
            quickSort(items, left, index - 1);
        }
        if (index < right) { // more elements on the right side of the pivot
            quickSort(items, index, right);
        }
    }
    return items;
}

// first call to quick sort
var items = [5, 3, 7, 6, 2, 9];
var result = quickSort(items, 0, items.length - 1);
console.log(result);

ieșire:

[ 2, 3, 5, 6, 7, 9 ]

Sortare rapidă completă Code

Combinând componentele swap, partition și recursivitate, se obține implementarea completă:

var items = [5, 3, 7, 6, 2, 9];

function swap(items, leftIndex, rightIndex) {
    var temp = items[leftIndex];
    items[leftIndex] = items[rightIndex];
    items[rightIndex] = temp;
}

function partition(items, left, right) {
    var pivot   = items[Math.floor((right + left) / 2)], // middle element
        i       = left,  // left pointer
        j       = right; // right pointer
    while (i <= j) {
        while (items[i] < pivot) {
            i++;
        }
        while (items[j] > pivot) {
            j--;
        }
        if (i <= j) {
            swap(items, i, j); // swapping two elements
            i++;
            j--;
        }
    }
    return i;
}

function quickSort(items, left, right) {
    var index;
    if (items.length > 1) {
        index = partition(items, left, right); // index returned from partition
        if (left < index - 1) { // more elements on the left side of the pivot
            quickSort(items, left, index - 1);
        }
        if (index < right) { // more elements on the right side of the pivot
            quickSort(items, index, right);
        }
    }
    return items;
}

// first call to quick sort
var sortedArray = quickSort(items, 0, items.length - 1);
console.log(sortedArray);

ieșire:

[ 2, 3, 5, 6, 7, 9 ]

Sortare rapida

Captura de ecran de mai sus prezintă programul complet în editor împreună cu matricea sortată din consolă. Această implementare a fost verificată în raport cu o matrice deja sortată, o matrice sortată invers, matrice care conțin valori duplicate și identice, numere negative, un singur element și o matrice goală și returnează rezultatul corect în fiecare caz.

💡 Sfat: Paznicul if (items.length > 1) verifică lungimea întregului tablou, nu intervalul curent. Funcționează aici deoarece cele două apeluri recursive sunt deja protejate de left < index - 1 și index < right, Dar if (left >= right) { return items; } este condiția cea mai clară și mai sigură pentru a scrie cod nou.

Complexitatea timpului și spațiului sortării rapide

Fiecare trecere de partiție atinge fiecare element din interval o singură dată, deci o singură trecere costă O(n). Prin urmare, costul total depinde de câte ori poate fi împărțită matricea înainte ca intervalele să devină triviale.

Caz Complexitatea timpului Când se întâmplă
Cel mai bune O (n jurnal n) Fiecare pivot își împarte raza de acțiune în două jumătăți de dimensiuni egale.
In medie O (n jurnal n) Intrare ordonată aleatoriu cu o regulă pivot rezonabilă.
Mini rulouri de absorbție O(n²) Fiecare pivot reprezintă cea mai mică sau cea mai mare valoare, oferind n niveluri de recursiune.

Complexitatea spațială este O(log n) pentru această versiune in-place. Nu este alocat niciun al doilea tablou, așa că singura memorie suplimentară este stiva recursivă, iar divizarea echilibrată menține acea stivă cu o adâncime de aproximativ log₂(n) cadre. În cel mai rău caz degenerat, stiva crește la O(n) cadre, motiv pentru care tablourile foarte mari pot depăși stiva de apeluri.

Două numere concretizează acest lucru. Sortarea a 4,096 de valori aleatorii cu codul de mai sus a folosit aproximativ 65,000 de comparații față de un n·log₂(n) teoretic de 49,152, iar cea mai profundă recursiune a atins 24 de cadre, în timp ce log₂(4096) este 12. Ambele cifre se încadrează în factorul constant mic așteptat de la un algoritm O(n log n).

⚠️ Atenție: Afirmația că Sortarea rapidă este pur și simplu „un algoritm O(n log n)” este incompletă. Cel mai rău caz este O(n²), iar un pivot naiv cu primul element lovește acel cel mai rău caz exact pe intrarea pe care este cel mai probabil să o primiți în producție: date care sunt deja sortate.

Sortare rapidă vs. alte sortări Algorithms

Sortarea rapidă este rareori singura opțiune. Tabelul de mai jos o compară cu ceilalți algoritmi pe care îi veți întâlni cel mai probabil, astfel încât să îl puteți alege pe cel potrivit pentru datele dvs.

Algoritm Cel mai bune In medie Mini rulouri de absorbție Spaţiu Stabil
Sortare rapida O (n jurnal n) O (n jurnal n) O(n²) O (jurnal n) Nu
Sortare îmbinare O (n jurnal n) O (n jurnal n) O (n jurnal n) O (n) Da
Sortare în grămadă O (n jurnal n) O (n jurnal n) O (n jurnal n) O (1) Nu
Sortare prin inserție O (n) O(n²) O(n²) O (1) Da
Bubble Sortare O (n) O(n²) O(n²) O (1) Da
Selecție Sortare O(n²) O(n²) O(n²) O (1) Nu

Sortarea rapidă este de obicei cea mai eficientă în practică, deoarece bucla sa internă este strânsă și funcționează în intervale contigue care acceptă memoria cache. Alegeți sortarea prin îmbinare atunci când aveți nevoie de o legătură O(n log n) garantată sau de o ordonare stabilă, sortarea heap atunci când memoria este extrem de constrânsă și sortarea prin inserție pentru matrice foarte mici sau aproape sortate. Bibliotecile de producție le combină frecvent: introsortarea începe cu sortarea rapidă, trece la sortarea heap dacă recursivitatea devine prea profundă și se termină cu sortarea prin inserție pe intervale mici.

Cum să sortați rapid obiecte și șiruri de caractere

Implementarea prezentată până acum compară valorile cu < și >, ceea ce îl restricționează la numere. Aplicațiile reale trebuie să sorteze obiecte printr-o proprietate, șiruri alfabetice sau date cronologice. Soluția este mutarea comparației într-o funcție de apel invers, exact ca în modul încorporat sort() nu.

Un comparator primește două valori și returnează un număr negativ atunci când prima ar trebui să fie prima, un număr pozitiv atunci când a doua ar trebui să fie prima și zero atunci când cele două sunt echivalente. Înlocuirea celor două comparații hard-coded cu apeluri de comparare face ca algoritmul să funcționeze pe orice tip de date.

function swap(items, i, j) {
    var temp = items[i];
    items[i] = items[j];
    items[j] = temp;
}

function partition(items, left, right, compare) {
    var pivot = items[Math.floor((right + left) / 2)],
        i     = left,
        j     = right;
    while (i <= j) {
        while (compare(items[i], pivot) < 0) { i++; }
        while (compare(items[j], pivot) > 0) { j--; }
        if (i <= j) {
            swap(items, i, j);
            i++;
            j--;
        }
    }
    return i;
}

function quickSort(items, left, right, compare) {
    if (left >= right) { return items; } // nothing left to split
    var index = partition(items, left, right, compare);
    if (left < index - 1) { quickSort(items, left, index - 1, compare); }
    if (index < right) { quickSort(items, index, right, compare); }
    return items;
}

function sort(items, compare) {
    compare = compare || function (a, b) { return a < b ? -1 : a > b ? 1 : 0; };
    return quickSort(items, 0, items.length - 1, compare);
}

var numbers = [10, 9, 1, 100, 25];
console.log(sort(numbers, function (a, b) { return a - b; }));

var names = ["Priya", "arun", "Bala", "chetan"];
console.log(sort(names, function (a, b) {
    return a.toLowerCase().localeCompare(b.toLowerCase());
}));

var employees = [
    { name: "Arun",   salary: 52000 },
    { name: "Bala",   salary: 41000 },
    { name: "Chetan", salary: 68000 }
];
console.log(sort(employees, function (a, b) { return a.salary - b.salary; }));

ieșire:

[ 1, 9, 10, 25, 100 ]
[ 'arun', 'Bala', 'chetan', 'Priya' ]
[
  { name: 'Bala', salary: 41000 },
  { name: 'Arun', salary: 52000 },
  { name: 'Chetan', salary: 68000 }
]

Trei detalii merită menționate. Garda recursivă este acum left >= right, care este corect pentru orice interval și nu depinde de lungimea matricei exterioare. Compararea șirurilor de caractere folosește localeCompare() astfel încât caracterele accentuate și majusculele și minusculele să fie gestionate corect în loc de punct de cod brut. Și deoarece Sortarea rapidă nu este stabilă, înregistrările care au același salariu își pot schimba locurile; sortați după o a doua cheie de departajare dacă ordinea originală este importantă pentru dvs.

Ești gata să continui? Consolidează elementele fundamentale cu JavaIntroducere în scenariu, exersează mecanica indicatorului în JavaBucle de script, lucrează prin mai multe practic JavaExemple de cod de script, comparați implementările în Sortare prin inserție și Sortare în grămadă, sau adăugați tipuri statice la acest algoritm cu TypeScript referinţă.

Întrebări frecvente

Nu. Sortarea rapidă schimbă elementele care se află la mare distanță, astfel încât două înregistrări cu chei egale pot ajunge într-o ordine relativă diferită față de cea inițială. Folosește sortarea prin îmbinare sau adaugă o a doua cheie de departajare la comparator, atunci când trebuie păstrată ordinea originală.

Hoare folosește doi indicatori care se mișcă unul spre celălalt și efectuează de aproximativ trei ori mai puține schimbări. Lomuto folosește un indicator de scanare și este mai ușor de citit. Codul de pe această pagină folosește o schemă cu doi indicatori în stil Hoare, cu un pivot la mijloc.

Da, la o intrare adversă unde recursivitatea atinge adâncimea de O(n). Protejați-vă de aceasta recurgând mai întâi în jumătatea mai mică și analizând.ping pe jumătatea mai mare, care limitează adâncimea stivei la O(log n), indiferent de modul în care cad pivoții.

Se poate, dar slab. Sortarea rapidă depinde de accesul aleatoriu în timp constant pentru a ajunge la pivotul din mijloc, lucru pe care o listă înlănțuită nu îl poate oferi. Sortarea prin îmbinare este alegerea standard pentru listele înlănțuite, deoarece necesită doar traversare secvențială și religare a pointerilor.

Aceștia combină frecvent un pivot Hoare cu limite de recurență Lomuto, producând erori de tip off-by-one sau bucle infinite pe valori duplicate. Datele eșantion ascund eroarea. Testați întotdeauna codul de sortare generat în raport cu tablouri sortate, sortate invers, cu multe duplicate și goale.

Da. Pasul său de partiționare alimentează Quickselect, care găsește a k-a cea mai mică valoare într-un timp mediu de O(n). Aceasta determină calculele mediane, recuperarea valorilor de top k în căutarea vectorială, reducerea valorilor aberante bazate pe percentile și selecția punctelor de divizare la antrenarea arborilor decizionali.

Rezumați această postare cu: