Tietojen lajittelumenetelmät - esitys. Lajittelumenetelmät

Tässä artikkelissa käsitellään matriisien lajittelun algoritmeja. Aluksi testaukseen valitut algoritmit esitetään lyhyt kuvaus heidän työstään, minkä jälkeen testaus suoritetaan suoraan, jonka tulokset syötetään taulukkoon ja tehdään lopulliset johtopäätökset.

Lajittelualgoritmeja käytetään hyvin laajalti ohjelmoinnissa, mutta joskus ohjelmoijat eivät edes ajattele, mikä algoritmi toimii parhaiten ("parhaan" käsite tarkoittaa sekä kirjoituksen että suorituksen nopeuden ja monimutkaisuuden yhdistelmää).

Tässä artikkelissa yritämme selvittää. Parhaan tuloksen saamiseksi kaikki esitetyt algoritmit lajittelevat 200 elementin kokonaislukumallin. Tietokoneella, jolla testaus suoritetaan, on seuraavat ominaisuudet: AMD A6-3400M 4x1,4 GHz -prosessori, 8 Gt RAM-muistia, Windows 10 x64 -rakenne 10586.36 -käyttöjärjestelmä.

Tutkimukseen valittiin seuraavat lajittelualgoritmit:

Valintalaji - Algoritmin ydin on kulkea matriisi alusta loppuun etsimällä matriisin minimielementtiä ja siirtää se alkuun. Tällaisen algoritmin monimutkaisuus on O (n2).

Kuplalaji - tämä algoritmi vaihtaa kaksi vierekkäistä elementtiä, jos ryhmän ensimmäinen elementti on suurempi kuin toinen. Näin tapahtuu, kunnes algoritmi vaihtaa kaikki lajittelemattomat kohteet. Tämän lajittelualgoritmin monimutkaisuus on O (n ^ 2).

Lisälaji - algoritmi lajittelee matriisin läpi sen elementtien. Kussakin iteraatiossa otetaan elementti ja verrataan kutakin elementtiä jo lajitellussa matriisin osassa, jolloin löydetään "oma paikka", jonka jälkeen elementti lisätään paikalleen. Tämä tapahtuu, kunnes algoritmi kulkee koko taulukon läpi. Lähtö on lajiteltu taulukko. Tämän algoritmin monimutkaisuus on O (n ^ 2).

Nopea lajittelu - Algoritmin ydin on jakaa matriisi kahteen alaryhmään, keskirivi on elementti, joka on matriisin keskellä. Algoritmin toiminnan aikana keskimääräistä pienemmät elementit siirretään vasemmalle ja suuret oikealle. Sama toiminto tapahtuu rekursiivisesti aliryhmästä, ne jaetaan vielä kahteen aliryhmään, kunnes on jotain jaettavaa (yksi elementti on jäljellä). Lähtö on lajiteltu taulukko. Algoritmin monimutkaisuus riippuu syötetiedoista ja on parhaimmillaan O (n × 2log2n). Pahin tapaus O (n ^ 2). On myös keskiarvo, joka on O (n × log2n).

Kampan lajittelu - Algoritmin idea on hyvin samanlainen kuin vaihtolajittelu, mutta tärkein ero on, että ei verrata kahta naapurielementtiä, vaan elementtejä aikavälillä, esimerkiksi viidessä elementissä. Näin vältetään eroon pienistä arvoista lopussa, mikä auttaa nopeuttamaan lajittelua suurissa ryhmissä. Ensimmäinen iterointi suoritetaan vaiheella, joka lasketaan kaavalla (matriisin koko) / (pelkistyskerroin), jossa pelkistyskerroin on noin 1,247330950103979 tai pyöristetty arvoon 1,3. Toinen ja sitä seuraavat iteraatiot suoritetaan vaiheella (nykyinen vaihe) / (vähennyskerroin) ja jatkuvat, kunnes vaihe on yhtä suuri. Lähes joka tapauksessa algoritmin monimutkaisuus on O (n × log2n).

Testausta varten suoritetaan 5 ajoa kustakin algoritmista ja valitaan paras aika. Paras käytetty aika ja muisti tallennetaan taulukkoon. Testataan myös 10, 50, 200 ja 1000 elementin matriisin lajittelunopeus sen määrittämiseksi, mihin tehtäviin tietty algoritmi on tarkoitettu.

Täysin lajittelematon taulukko:

Osittain lajiteltu taulukko (puolet elementeistä on järjestetty):

Tulokset esitetään kaavioina:

Tutkimuksen ja saatujen tietojen perusteella lajittelemattoman taulukon lajittelua varten optimaalisin esitetyistä algoritmeista taulukon lajittelemiseksi on nopea lajittelu. Pidemmästä toteutusajasta huolimatta algoritmi kuluttaa vähemmän muistia, mikä voi olla tärkeää suurissa projekteissa. Algoritmit, kuten valinta, vaihto ja lisäyslajittelu, voivat kuitenkin soveltua paremmin tieteellisiin tarkoituksiin, kuten opetukseen, joissa ei tarvitse käsitellä valtavia määriä tietoa. Osittain lajitellun taulukon tulokset eivät ole kovin erilaisia, kaikki lajittelualgoritmit osoittavat aikaa noin 2-3 millisekuntia vähemmän. Kun lajitellaan osittain lajiteltu taulukko, pikalajitelma on paljon nopeampi ja käyttää vähemmän muistia.

Artikkelissa käsitellään joitain suosituimpia taulukoiden lajittelualgoritmeja, joita käytetään sekä käytännössä että opetustarkoituksiin. Haluan tehdä varauksen heti, että kaikki tarkastellut algoritmit ovat hitaampia kuin menetelmä, jolla taulukko lajitellaan klassisen arvolistan kautta, mutta ne ansaitsevat kuitenkin huomion. Saan paljon tekstiä, joten kuvaan kullekin algoritmille perustavanlaatuisimmat.

1. Algoritmi "Lajittele valinnan mukaan".

Se on yksi yksinkertaisimmista taulukon lajittelualgoritmeista. Tarkoitus on käydä matriisin läpi ja etsiä aina matriisin vähimmäiselementti, vaihtamalla se matriisin lajittelemattoman osan alkuelementin kanssa. Pienillä matriiseilla se voi olla jopa tehokkaampi kuin monimutkaisemmat lajittelualgoritmit, mutta joka tapauksessa se häviää suurilla matriiseilla. Elementtien vaihdon lukumäärä "kupla" -algoritmiin nähden on N / 2, missä N on matriisielementtien lukumäärä.

Algoritmi:
1. Etsi matriisin vähimmäisosa.
2. Muuta minimin ja ensimmäisen elementin paikkoja paikoissa.
3. Etsimme jälleen minimielementtiä taulukon lajittelemattomasta osasta
4. Korvaa matriisin toinen elementti ja löydetty minimi, koska matriisin ensimmäinen elementti on lajiteltu osa.
5. Etsi minimiarvot ja vaihda elementtejä, kunnes taulukko on lajiteltu loppuun asti.

// Lajittele valinnan mukaan (--- Toiminto Lajittele Lajittele valinnan mukaan (Arvotaulukko) Min \u003d 0; Jos i \u003d 0 Matriisin mukaan.Raja () Sykli Min \u003d i; Jos j \u003d i + 1 Matriisin mukaan.Raja () Silmukka / / Etsitään matriisin minimielementtiä Jos taulukko [j]< Массив[Мин] Тогда Мин = j; КонецЕсли; КонецЦикла; Если Массив [Мин] = Массив [i] Тогда //Если мин. элемент массива = первому элементу неотс. части массива, то пропускаем. Продолжить; КонецЕсли; Смена = Массив[i]; //Производим замену элементов массива. Массив[i] = Массив[Мин]; Массив[Мин] = Смена; КонецЦикла; Возврат Массив; КонецФункции

2. Algoritmi "Bubble sort".

Ehkä tunnetuin algoritmi, jota käytetään opetustarkoituksiin, on liian hidas käytännön käyttöön. Algoritmi on monimutkaisempien algoritmien taustalla: "Shaker Sort", "Heap Sort", "Quick Sort". On huomionarvoista, että yksi nopeimmista algoritmeista "Nopea algoritmi" kehitettiin päivittämällä yksi pahimmista algoritmeista "Bubble Sort". "Nopea" ja "Shaker" -lajikkeista keskustellaan myöhemmin. Algoritmin tarkoitus on, että matriisin "kevyimmät" elementit näyttävät "kelluvan" ja "raskaimmat" "uppoavat". Siksi nimi "Bubble Sort"

Algoritmi:
1. Matriisin kutakin elementtiä verrataan seuraavaan ja jos elementti [i]\u003e korvataan. Siten "kevyimmät" elementit "kelluvat" - siirtyvät luettelon alkuun ja raskain "pesuallas" - siirtyvät loppuun.
2. Toista vaihe 1 n-1 kertaa, jossa n on Array.Määrä ().

// Bubble Sort (--- Funktio Bubble Sort (Value Array) For i \u003d 0 Array.Boundary () Loop For j \u003d 0 Array.Boundary () - i - 1 Loop If Array [j]\u003e Array Then Replacement \u003d Array [j]; Array [j] \u003d Array; Array \u003d Korvaa; EndIf; EndLoop; EndLoop; Return Array; EndFunction // ---)

3. "Shaker sort" -algoritmi (Satunnainen lajittelu, Kaksisuuntainen kuplalajittelu).

Algoritmi on yksi edellisen lajittelun - "kupla lajittelu" - versioista. Tärkein ero on, että klassisessa kuplalajittelussa elementit liikkuvat alhaalta ylöspäin yhteen suuntaan, kun taas ravistimen lajittelussa ensin liikutaan alhaalta ylöspäin ja sitten ylhäältä alas.

Algoritmi on sama kuin kuplalajittelussa + ylhäältä alas -jakso lisätään.

Alla olevassa esimerkissä ravistimen luokittelu on parantunut. Toisin kuin klassinen, se käyttää kaksi kertaa vähemmän iteraatioita.

// Lajittele satunnaistoisto (Shaker-Lajittele) (--- Funktio SortShuffle (Taulukon arvo) Jos i \u003d 0 PO Array.Boundary () / 2 Loop nIter \u003d 0; conIter \u003d Array.Boundary (); Vaikka nIter Array [nIter + 1] Sitten Korvaus \u003d Taulukko [nIter]; Taulukko [nIter] \u003d Taulukko [nIter + 1]; Taulukko [nIter + 1] \u003d Korvaus; EndIf; nIter \u003d nIter + 1; // Siirrä paikkaa yksi askel eteenpäin // Siirry loppu Jos Array [conIter - 1]\u003e Array [conIter] Sitten Replacement \u003d Array [conIter - 1]; Array [conIter-1] \u003d Array [conIter]; Array [conIter] \u003d Replacement; EndIf; conIter \u003d conIter - 1 ; // Siirrä asemaa yksi askel taaksepäin Silmukan loppu; Silmukan loppu; Palautusryhmä; Lopetustoiminto // ---)

4. Algoritmi "Kääpiölajittelu".

Algoritmi on niin oudosti nimetty hollantilaisen tutkijan Dick Grunin ansiosta.

Kääpiölajittelu perustuu tekniikkaan, jota hollantilainen puutarhatonttu (hollantilainen tuinkabouter) käyttää. Tätä menetelmää puutarhatonttu lajittelee kukkaruukut. Pohjimmiltaan hän tarkastelee seuraavaa ja edellistä puutarhaa: jos ne ovat oikeassa järjestyksessä, hän astuu eteenpäin yhden potin, muuten hän vaihtaa ne ja astuu yhden potin takaisin. Rajaolosuhteet: jos edellistä pottia ei ole, se siirtyy eteenpäin; jos ei ole seuraavaa pottia, hän on valmis.
Dick Grun

Se on itse asiassa "Dwarven sorting" -algoritmin koko kuvaus. Mielenkiintoista on, että algoritmi ei sisällä sisäkkäisiä silmukoita, vaan lajittelee koko matriisin yhdellä kertaa.

// Dwarf Sort (--- Dwarven Sort Function (Value Array) i \u003d 1; j \u003d 2; Vaikka i< Массив.Количество() Цикл // Сравнение < - Сортировка по возрастанию, > - laskeva Jos taulukko i \u003d j; j \u003d j + 1; Muuten Korvaus \u003d Taulukko [i]; Taulukko [i] \u003d Taulukko; Taulukko \u003d Korvaa; i \u003d i - 1; Jos i \u003d 0, niin i \u003d j; j \u003d j + 1; Loppu Jos; Loppu Jos; Syklin loppu; Return Array; EndFunction // ---)

5. Algoritmi "Lajittele inserttien mukaan".

Se on yksinkertainen lajittelualgoritmi. Asia on, että jokaisessa vaiheessa otamme elementin, etsimme sen sijainnin ja asetamme sen oikeaan paikkaan.
Alkuesimerkki: Pelatessasi hölmöä, vedät kortin kannelta ja työnnät sen oikeaan paikkaan nousevassa järjestyksessä sinulla olevissa korteissa. Tai
myymälässä he antoivat sinulle 550 ruplaa - yhden 500, toisen 50 setelin. Katsot lompakkoon, ja seteleitä on 10 100 1000. Lisää lasku
arvoinen 50 ruplaa. 10r- ja 100r-seteleiden välillä ja 500-ruplaisten 100--1000r-setelien välillä. Tulee 10,50,100,500,1000 - Tässä on sinulle
ja "Lajittelu lisäysten mukaan" -algoritmi.
Siksi algoritmin jokaisessa vaiheessa sinun on lajiteltava tietojen alikartta ja lisättävä arvo oikeaan paikkaan.


// lisäyslajittelu (--- funktion lisäyslajittelu (arvotaulukko) i \u003d 0 matriisin mukaan.Raja () - 1 silmukka-avain \u003d i + 1; korvaus \u003d taulukko [avain]; j \u003d i + 1; kun j\u003e 0 Ja korvaaminen< Массив Цикл Массив[j] = Массив; Замена = j - 1; Ключ = j - 1; j = j - 1; КонецЦикла; Массив[Ключ] = Замена; КонецЦикла; Возврат Массив; КонецФункции //---}

6. Algorim "Yhdistä lajittelu".

Mielenkiintoinen algoritmi toteutuksen ja idean kannalta. Sen tarkoitus on jakaa matriisi aliriveihin, kunnes kunkin alirakenteen pituus on yhtä suuri kuin 1. Sitten väitämme, että tällainen alirakenne on lajiteltu. Sitten yhdistetään saadut alirakenteet yhteen ja verrataan ja lajitellaan alirakenteiden arvoja samanaikaisesti elementtien mukaan.

p / s ei voinut lisätä tähän kuvaa, jossa olisi visuaalisempi kaavio, se tahriintuu jatkuvasti. Mutta se näkyy selvästi alla olevassa kuvakaappauksissa. Näet kuinka algoritmi toimii.

// Lajittele yhdistämisen mukaan (---

Funktio SortMerge (Value Array) Jos Array.Number () \u003d 1 Sitten Return Array; Loppu Jos; Katkaisupiste \u003d Taulukon numero () / 2; lArray \u003d Uusi taulukko; prArray \u003d Uusi taulukko; Jos Mf \u003d 0 PO Array.Boundary () -sykli Jos Mf< ТочкаРазрыв Тогда лМассив.Добавить(Массив[Сч]); Иначе прМассив.Добавить(Массив[Сч]); КонецЕсли; КонецЦикла; Возврат Слияние(СортировкаСлиянием(лМассив),СортировкаСлиянием(прМассив)); КонецФункции Функция Слияние(массив1,массив2) a = 0; b = 0; слМассив = Новый Массив; Для Сч = 0 ПО (Массив1.Количество() + Массив2.Количество())-1 Цикл слМассив.Добавить(); КонецЦикла; Для i = 0 ПО (массив1.Количество() + массив2.Количество())-1 Цикл Если b < массив2.Количество() И a < массив1.Количество() Тогда Если (массив1[a] > taulukko2 [b]) JA (b< массив2.Количество()) Тогда слМассив[i] = массив2[b]; b = b + 1; Иначе слМассив[i] = массив1[a]; a = a + 1; КонецЕсли; Иначе Если b < массив2.количество() Тогда слМассив[i] = массив2[b]; b = b + 1; Иначе слМассив[i] = массив1[a]; a = a + 1; КонецЕсли; КонецЕсли; КонецЦикла; Возврат слМассив; КонецФункции //---}

7. Algorim "Kuoren lajittelu".

Algoritmi on nimetty amerikkalaisen tutkijan Donald Schellin mukaan. Ytimessä tämä algoritmi on parannettu Insert Sort -algoritmi. Algoritmin tarkoitus on verrata paitsi vierekkäisten elementtien lisäksi myös tietyllä etäisyydellä olevia elementtejä. Ensin valitaan vaihe - tietty intervalli, jonka läpi taulukkoelementtejä verrataan kullakin iteraatiolla. Se määritellään yleensä seuraavasti:
Ensimmäisessä iterointivaiheessa \u003d kokonaisluku (Array.Quantity () / 2), seuraavassa iterointivaiheessa \u003d kokonaisluku (vaihe / 2). Nuo. vaihetta pienennetään vähitellen ja kun vaihe on yhtä suuri kuin 1, viimeinen vertailu tapahtuu ja taulukko lajitellaan.

Esimerkki:
Annetaan taulukko (10,5,3,1,14,2,7,12).
1. Vaihe \u003d 4.
Lajittele yksinkertaisilla lisäyksillä jokainen 4 elementin ryhmää (10.14) (5.2) (3.7) (1.12)

10 ,2 ,3 ,1,14 ,5 ,7 ,12

2. Vaihe \u003d 2
Lajittele yksinkertaisilla lisäyksillä jokainen 4 elementin ryhmä (10,3,14,7) (2,1,5,12)

3 ,1 ,7 ,2 ,10 ,5 ,14 ,12

3. Vaihe \u003d 1
Lajittelemme yksinkertaisilla lisäyksillä jokainen 8 elementin ryhmä.

1,2,3,5,7,10,12,14


// Kuorilajittelu (--- Funktio Kuorilajittelu (taulukon arvo) Vaihe \u003d Kokonaisluku (Taulukon numero () / 2); Vaikka Vaihe\u003e 0 Silmukka i \u003d 0; Vaikka i< (Массив.Количество() - Шаг) Цикл j = i; Пока j >\u003d 0 JA Taulukko [j]\u003e Taulukon silmukka Korvaa \u003d Taulukko [j]; Taulukko [j] \u003d Taulukko; Taulukko \u003d Korvaa; j \u003d j - 1; Jos ApplyDisplaySort sitten DisplaySort Chart (taulukko); Loppu Jos; Syklin loppu; i \u003d i + 1; Syklin loppu; Vaihe \u003d Int (vaihe / 2); HandleUserInterrupt (); Syklin loppu; Return Array; EndFunction // ---)

8. Algoritmi "Nopea lajittelu".

Suosituin ja käytetyin algoritmi käytännössä. Se on yksi tehokkaimmista tietojen lajittelualgoritmeista.
Algoritmin koko tarkoitus on hajottaa monimutkainen ongelma pieniksi ja ratkaista ne erikseen. Tietty vertailupiste valitaan ja kaikki pienemmät arvot heitetään vasemmalle, kaikki muut oikealle. Lisäksi se tekee jokaiselle saadulle osalle saman, kunnes osia ei ole enää mahdollista jakaa. Loppujen lopuksi saamme paljon lajiteltuja osia, jotka meidän on vain liimattu yhteen kokonaisuuteen.

// Algoritmi "Nopea lajittelu" (menettely b_Sort (matriisi, alaraja, yläraja) i \u003d alaraja; j \u003d ylempi raja; m \u003d matriisi [kokonaisluku ((i + j) / 2)]; tosisyklin aikana [i]< m Цикл i = i + 1; КонецЦикла; Пока Массив[j] > m sykli j \u003d j - 1; Syklin loppu; Jos i\u003e j Sitten keskeytä; Loppu Jos; Syklin loppu; Jos alaraja< j Тогда б_Сортировка(Массив,НижнийПредел,j); КонецЕсли; Если i < ВерхнийПредел Тогда б_Сортировка(Массив,i,ВерхнийПредел); КонецЕсли; КонецПроцедуры Функция БыстраяСортировка(Массив) НижняяГраница = 0; ВерхняяГраница = Массив.ВГраница(); б_Сортировка(Массив,НижняяГраница,ВерхняяГраница); Возврат Массив; КонецФункции //---}

9. Taulukon klassinen lajittelu 1 sekunnissa.

Välitämme taulukon arvoluettelolle. Lajittele tavallisella "Lajittele" -menetelmällä.

// Lajittelu arvoluettelon mukaan (--- Funktio Lajittelu arvoluettelon mukaan (ArrayValue) mListVal \u003d NewList ofValues; mListValues.ListValues \u200b\u200b(Array); mListValues.SortBy Value (Lajittelusuunta.Activate); Return mDownloadListValues.Value.


Kaikenlaisia \u200b\u200bvoidaan nopeuttaa järjestämällä koodi silmukoiksi yhdelle riville. Mutta luettavuuden vuoksi jätin sen niin.


Kirjoitettu käsittely, jossa kaikki yllä olevat algoritmit on toteutettu, myös lajitteluprosessin dynaamista animaatiota tuetaan (Paitsi tavallinen 1c-lajittelu) .

-Käsittelyn alkaessa luodaan automaattisesti joukko satunnaisia \u200b\u200blukuja 0-100, joiden koko on 100 elementtiä.
-Luo toinen taulukko napsauttamalla "Luo RNG-taulukko" -painiketta, voit myös valita tarvittavan alueen.
-Jos haluat ottaa dynaamisen animaation käyttöön, valitse "Näytä lajittelu kaaviossa" -valintaruutu. Kehotan sinua valitsemaan tehottomien algoritmien valintaruudun, kun matriisimitta on enintään 100 elementtiä, muuten olet vanha odottamaan lajittelua :)

Lajitteluprosessin dynaaminen renderointi vähentää huomattavasti suorituskykyä, mutta voit selvästi nähdä, kuinka algoritmi toimii.

Johdanto .

Noin kolme ja puoli vuosikymmentä on kulunut tietokoneohjelmoinnin käyttöönotosta akateemisena tieteenalana pedagogisissa yliopistoissa. Koska itse aiheen valtava muutosnopeus ylitti aina merkittävästi keskitettyjen julkaisumekanismien määrän, erityisesti pedagogisten yliopistojen ohjelmille suunnattuja kirjoja julkaistiin enintään kerran vuosikymmenessä - melkein suhteessa tietokoneiden sukupolvien muutosnopeuteen. Nykyään kirjakaupan hyllyt ovat täynnä tietojenkäsittelytieteen julkaisuja. Opettaja (ja ennen kaikkea opiskelija) tarvitsee kuitenkin erityisiä oppikirjoja, joiden sisältö ja suunta vastaavat ilmoitettua opetussuunnitelmaa ja ohjelmaa. Joidenkin erikoisalojen ohjelmoinnin lisäksi pedagogiset yliopistot ovat ottaneet käyttöön muita monimutkaisempia erikoiskursseja soveltavan (erillisen) matematiikan ja tietojenkäsittelytieteen risteyksessä.

Tässä kurssityössä voit tutustua matriiseihin ja oppia yksinkertaisista ja monimutkaisista menetelmistä niiden lajittelemiseksi sekä siitä, mitkä niistä ovat tehokkaimpia ja missä tapauksissa.

1. Tehtävien lajittelu.

1.1 Yleiset säännökset.

Päätehtävänä on esitellä erilaisia \u200b\u200blajittelumenetelmiä ja korostaa tehokkaimpia. Lajittelu on melko hyvä esimerkki ongelmasta, joka voidaan ratkaista monilla eri algoritmeilla. Jokaisella niistä on omat edut ja haitat, ja sinun on valittava algoritmi ongelman erityisen muotoilun perusteella.

Yleensä lajittelun tulisi olla prosessi, jolla tietty objektijoukko järjestetään uudelleen tietyssä järjestyksessä. Lajittelun tarkoituksena on helpottaa kohteiden löytämistä myöhemmin tällaisesta lajitellusta joukosta. Tämä on melkein universaali, perustoiminta. Tapaamme lajiteltuja esineitä puhelinluetteloissa, tuloverolistoissa, kirjojen sisältöluettelossa, kirjastoissa, sanakirjoissa, varastoissa - melkein kaikkialta, mistä meidän on etsittävä tallennettuja esineitä.

Siten lajittelusta puhuminen on varsin tarkoituksenmukaista ja tärkeää tietojen käsittelyssä. Alun perin kiinnostuksemme lajitteluun perustuu siihen tosiasiaan, että kohtaamme monia hyvin perustavanlaatuisia temppuja algoritmeja rakennettaessa. Melkein ei ole menetelmiä, joita sinun ei tarvitse tavata keskustellessasi tästä ongelmasta. Erityisesti lajittelu on ihanteellinen kohde valtavan monien algoritmien esittelyyn, ne kaikki on keksitty samaan ongelmaan, monet ovat jossakin mielessä optimaalisia, useimmilla on omat etunsa. Siksi se on myös ihanteellinen kohde, joka osoittaa tarpeen analysoida algoritmien suorituskykyä. Lisäksi esimerkit lajittelusta voivat osoittaa, kuinka monimutkaisella algoritmilla voit saavuttaa merkittävän hyötysuhteen, vaikka käytettävissä on jo ilmeisiä menetelmiä.

Algoritmin valinta riippuu käsiteltävän datan rakenteesta - tämä on melkein laki, mutta lajittelun tapauksessa tällainen riippuvuus on niin syvä, että vastaavat menetelmät jaettiin kahteen luokkaan - taulukoiden lajittelu ja tiedostojen (sekvenssit) lajittelu ). Joskus niitä kutsutaan sisäiseksi ja ulkoiseksi lajitteluksi, koska taulukot tallennetaan koneen nopeaan, satunnaismuistiin ja tiedostot sijaitsevat yleensä hitaammassa, mutta myös kapeammassa ulkoisessa muistissa mekaanisiin liikkeisiin perustuvilla laitteilla (levyt tai nauhat) ...

, a, ……, muuten lajittelu on näiden elementtien permutaatio taulukkoon ak, ak, ……, ak missä ak<= ak <= ….. <= ak.

Oletetaan, että elementtityypiksi määritetään INTEGER.

Constn \u003d ???; // taulukon vaadittu pituus ilmoitetaan tässä

Muuttuja A: kokonaisluku;

INTEGERin valinta on jonkin verran mielivaltainen. Voisit ottaa ja

toinen tyyppi, jolle määritetään yleinen järjestyssuhde.

Lajittelumenetelmää kutsutaan pysyväksi, jos lajitteluprosessi ei muuta elementtien suhteellista sijaintia samoilla avaimilla. Vakauden lajittelu on usein toivottavaa, kun on kyse tuotteista, jotka on jo järjestetty (lajiteltu) jonkin toissijaisen avaimen (eli ominaisuuksien) perusteella, jotka eivät vaikuta ensisijaiseen avaimeen.

1.2. Lausunto matriisien lajittelun ongelmasta.

Tärkein ehto: valitun taulukoiden lajittelutavan tulisi käyttää käytettävissä olevaa muistia säästeliäästi. Tämä merkitsee sitä, että elementtien järjestyksen suorittavat permutaatiot tulisi suorittaa samassa paikassa, toisin sanoen menetelmät, joissa elementit ryhmästä a siirretään tuloksena olevaan ryhmään b, ovat paljon vähemmän kiinnostavia. Luokitellaan ensin menetelmät niiden kustannustehokkuuden mukaan, toisin sanoen niiden käyttöajan mukaan. Hyvä tehokkuuden mitta voi olla C, tarvittavien avainvertailujen määrä ja M, elementtisiirtojen määrä (permutaatiot). Nämä luvut ovat n: n funktioita - lajiteltavien elementtien lukumäärä. Vaikka hyvät lajittelualgoritmit vaativat n * logn-vertailun järjestyksen, hajotetaan ensin muutama yksinkertainen ja ilmeinen menetelmä, nimeltään suora, missä järjestys n2-avaimen vertailuja vaaditaan. Seuraavat syyt pakottavat meidät jäsentämään suorilla menetelmillä koskematta nopeisiin algoritmeihin:

1. Suorat menetelmät ovat erityisen hyödyllisiä selittäessä useimpien lajittelun perusperiaatteita.

2. Näiden menetelmien ohjelmat ovat helposti ymmärrettäviä ja lyhyitä.

3. Monimutkaiset menetelmät vaativat suuren määrän operaatioita, ja siksi riittävän pienelle n: lle suorat menetelmät osoittautuvat nopeammin, vaikka niitä ei tietenkään pitäisi käyttää suurille n: lle.

Paikalliset lajittelumenetelmät voidaan jakaa kolmeen pääluokkaan niitä määrittelevien periaatteiden mukaisesti:

· Lajittelu sisällyttämisen mukaan (lisääminen).

· Lajittelu käyttämällä valintaa (byselection).

· Lajittelu pörssien avulla (byexchange).

Tutkimme nyt näitä periaatteita ja vertaamme niitä. Kaikki ohjelmat toimivat taulukossa a.

Constn \u003d<длина массива>

a: kokonaisluku;

2. Taulukoiden lajittelumenetelmät.

2.1. Yksinkertaiset menetelmät taulukoiden lajittelussa.

2.1.1. Lajittelu suoran sisällyttämisen mukaan.

Tätä menetelmää käytetään laajasti kortteja pelattaessa. Elementit on henkisesti jaettu "valmiiksi" jaksoksi a

,…, Mutta myös alkuperäinen järjestys. Kussakin vaiheessa, alkaen arvosta I \u003d 2 ja lisäämällä i: tä joka kerta kerralla, i: nnet elementit uutetaan alkuperäisestä sekvenssistä ja siirretään valmiiseen sekvenssiin samalla, kun se lisätään haluttuun paikkaan.

OHJELMA 2.1. Lajittelu suoran mukaan ottamisen mukaan.

I, J, N, X: INTEGER;

A: INTEGERIN ARRAY;

WRITELN ('Syötä taulukon pituus');

WRITELN ('Anna taulukko');

SINUN I: \u003d 1 TO N LUE (A [I]);

SINUN I: \u003d 2 TO N DO

X: n aikana

WRITELN ("Tulos:");

MINULLE: \u003d 1 - N N KIRJOITA

Tällainen tyypillinen tapaus toistuvasta prosessista kahdella ehdolla

valmistuminen antaa meille mahdollisuuden käyttää tunnettua temppua

"Este" (vartija).

Suoran inkluusiomenetelmän analyysi. Keskeisten vertailujen (Ci) lukumäärä i-sessä seulonnassa on korkeintaan i-1, vähintään 1; jos oletetaan, että kaikki n avaimen permutaatiot ovat yhtä todennäköisiä, keskimääräinen vertailumäärä on I / 2. Siirtojen määrä Mi on yhtä suuri kuin Ci + 2 (mukaan lukien este). Siksi vertailujen kokonaismäärä ja siirtojen määrä ovat seuraavat:

Cmin \u003d n-1 (2.1.) Mmin \u003d 3 * (n-1) (2.4.)

Luola \u003d (n2 + n-2) / 4 (2.2.) Mave \u003d (n2 + 9 * n-10) / 4 (2.5.)

Cmax \u003d (n2 + n-4) / 4 (2.3.) Mmax \u003d (n2 + 3 * n-4) / 2 (2.6.)

Suoran sisällyttämisen algoritmia voidaan parantaa helposti, jos kiinnität huomiota siihen, että valmis sekvenssi, johon sinun on lisättävä uusi elementti, on jo tilattu itse. On luonnollista pysyä binäärihaussa, jossa yritetään verrata valmiin sekvenssin keskiosaan, ja sitten jakaminen puoliksi jatkuu, kunnes inkluusiopiste löytyy. Tätä muokattua lajittelualgoritmia kutsutaan binääriseksi lisäykseksi.

OHJELMA 2.2. Lajittelu sukupuolen mukaan jaettavan menetelmän mukaan.

I, J, M, L, R, X, N: INTEGER;

A: INTEGERIN ARRAY;

WRITELN ("Anna taulukon pituus");

WRITELN ("Anna taulukko");

SINUN I: \u003d 1 TO N LUE (A [I]);

SINUN I: \u003d 2 TO N DO

X: \u003d A [I]; L: \u003d 1; R: \u003d I;

JOS A [M]<=X THEN L:=M+1 ELSE R:=M

Koodin yksinkertaistamiseksi ja luettavuuden parantamiseksi otamme käyttöön Swap-menetelmän, joka vaihtaa taulukon arvot hakemistojen mukaan.

Void Swap (T-kohteet, int vasen, int oikea) (jos (vasen! \u003d Oikea) (T-lämpötila \u003d kohteet; kohteet \u003d kohteet; kohteet \u003d lämpötila;))

Kuplalaji

Bubble Sort on yksinkertaisin lajittelualgoritmi. Se kulkee taulukon läpi useita kertoja siirtäen suurimman lajittelemattoman arvon taulukon loppuun kussakin vaiheessa.

Esimerkiksi meillä on joukko kokonaislukuja:

Ensimmäisen kerran, kun siirryt matriisin läpi, verrataan arvoja 3 ja 7. Koska 7 on suurempi kuin 3, jätämme ne sellaisiksi kuin ne ovat. Sitten verrataan 7: tä ja 4: ää. 4 on alle 7, joten vaihdamme ne, siirtämällä 7: tä yhden sijainnin lähemmäksi taulukon päätä. Se näyttää nyt tältä:

Tätä prosessia toistetaan, kunnes 7 saavuttaa melkein matriisin lopun. Lopussa sitä verrataan elementtiin 8, joka on suurempi, mikä tarkoittaa, että vaihtoa ei ole. Kun olet kulkenut taulukon kerran, se näyttää tältä:

Koska arvojen vaihto on ollut ainakin yksi, meidän on toistettava taulukko uudelleen. Tämän kohdan seurauksena siirrämme numero 6 paikalleen.

Ja jälleen, ainakin yksi vaihto tehtiin, mikä tarkoittaa, että käymme läpi ryhmän uudelleen.

Seuraavan siirron aikana ei suoriteta vaihtoa, mikä tarkoittaa, että matriisimme on lajiteltu ja algoritmi on saanut työnsä päätökseen.

Public void Lajittelu (T-kohteet) (bool vaihdettu; do (vaihdettu \u003d false; for (int i \u003d 1; i< items.Length; i++) { if (items.CompareTo(items[i]) > 0) (Vaihda (kohteet, i - 1, i); vaihdettu \u003d tosi;))) kun taas (vaihdettu! \u003d Väärä); )

Lajittele inserttien mukaan

Lisälajittelu toimii kävelemällä taulukon läpi ja siirtämällä haluttu arvo taulukon alkuun. Kun seuraava sijainti on käsitelty, tiedämme, että kaikki sijainnit ennen sitä on lajiteltu, mutta ei sen jälkeen.

Tärkeä seikka: lisäyslajittelu käsittelee matriisin elementit järjestyksessä. Koska algoritmi silmukkaa elementtien läpi vasemmalta oikealle, tiedämme, että kaikki nykyisen hakemiston vasemmalla puolella on jo lajiteltu. Tämä kuva osoittaa, kuinka taulukon lajiteltu osa kasvaa jokaisen siirron yhteydessä:

Matriisin lajiteltu osa kasvaa vähitellen, ja lopulta taulukko järjestetään.

Katsotaanpa tiettyä esimerkkiä. Tässä on käyttämämme lajittelematon taulukko:

Algoritmi alkaa indeksistä 0 ja arvosta 3. Koska tämä on ensimmäinen indeksi, matriisi siihen asti mukaan lukien katsotaan lajitelluksi.

Tässä vaiheessa elementit, joiden indeksit ovat 0..1, lajitellaan, mutta elementeistä, joiden indeksit ovat 2..n, ei tiedetä mitään.

Seuraava tarkistus on arvo 4. Koska se on alle seitsemän, meidän on siirrettävä se oikeaan kohtaan taulukon lajitellussa osassa. Kysymys on edelleen: kuinka se määritetään? Tämä tapahtuu FindInsertionIndex-menetelmällä. Se vertaa sille välitettyä arvoa (4) lajiteltuun osaan kuuluviin arvoihin, kunnes löytää paikan lisätä.

Joten löysimme indeksin 1 (arvojen 3 ja 7 välillä). Insert-menetelmä suorittaa lisäyksen poistamalla lisätyn arvon taulukosta ja siirtämällä kaikki arvot indeksistä alkaen lisäämällä oikealle. Matriisi näyttää nyt tältä:

Nyt matriisin osa, joka alkaa nollaelementistä ja päättyy indeksillä 2 olevaan elementtiin, on lajiteltu. Seuraava siirto alkaa indeksistä 3 ja arvosta 4. Algoritmin edetessä jatkamme tällaisten lisäysten tekemistä.

Kun lisäyksiä ei ole enää, taulukko katsotaan täysin lajitelluksi ja algoritmi on valmis.

Julkinen mitätön Lajittelu (T kohdetta) (int sortedRangeEndIndex \u003d 1; while (sortedRangeEndIndex< items.Length) { if (items.CompareTo(items) < 0) { int insertIndex = FindInsertionIndex(items, items); Insert(items, insertIndex, sortedRangeEndIndex); } sortedRangeEndIndex++; } } private int FindInsertionIndex(T items, T valueToInsert) { for (int index = 0; index < items.Length; index++) { if (items.CompareTo(valueToInsert) > 0) (paluuindeksi;)) heittää uusi InvalidOperationException ("Lisäysindeksiä ei löydy"); ) private void Insert (T itemArray, int indexInsertingAt, int indexInsertingFrom) (// itemArray \u003d 0 1 2 4 5 6 3 7 // insertingAt \u003d 3 // insertingFrom \u003d 6 // // Toiminnot: // 1: Tallenna nykyinen indeksi lämpötilassa // 2: Korvaa indexInsertingAt indeksilläInsertingFrom // 3: Korvaa indexInsertingAt indeksillä indexInsertingFrom sijainnissa +1 // Siirrä kohteita yksi kerrallaan. // 4: Kirjoita lämpötila matriisiin + 1. // Vaihe 1. T temp \u003d itemArray; // Vaihe 2.itemArray \u003d itemArray; // Vaihe 3.for (int current \u003d indexInsertingFrom; current\u003e indexInsertingAt; current--) (itemArray \u003d itemArray;) // Vaihe 4.itemArray \u003d temp;)

Valintalaji

Valintalajittelu on eräänlainen yhdistelmä kuplalajittelun ja lisäyslajittelun välillä. Kuten kupla-lajittelussa, tämä algoritmi toistuu taulukon yli ja uudelleen ja siirtää yhden arvon oikeaan kohtaan. Toisin kuin kuplalajittelu, se valitsee kuitenkin pienimmän lajittelemattoman arvon suurimman sijasta. Kuten lisäyslajittelun kohdalla, taulukon lajiteltu osa on alussa, kun taas kuplalajittelussa se on lopussa.

Katsotaanpa, kuinka valintalajittelu toimii lajittelemattomassa taulukossa.

Ensimmäisellä kerralla algoritmi yrittää löytää matriisin pienimmän arvon ja siirtää sen alkuun käyttämällä FindIndexOfSmallestFromIndex-menetelmää.

Tällaisella pienellä ryhmällä voimme heti kertoa, että pienin arvo on 3, ja se on jo oikeassa asennossa. Tässä vaiheessa tiedämme, että pienin arvo on taulukon ensimmäisessä paikassa (indeksi 0), joten taulukon alku on jo lajiteltu. Siksi aloitamme toisen siirron - tällä kertaa indekseillä 1 - n - 1.

Toisella kierroksella määritetään, että pienin arvo on 4. Vaihdamme sen toiseen elementtiin, seitsemään, jonka jälkeen 4 siirtyy oikeaan asentoonsa.

Nyt taulukon lajittelematon osa alkaa hakemistosta 2. Se kasvaa yhdellä elementillä kutakin algoritmin läpäisyä kohden. Jos missään passissa emme tehneet yhtä vaihtoa, se tarkoittaa, että taulukko on lajiteltu.

Kahden uuden kierroksen jälkeen algoritmi suorittaa työnsä loppuun:

Julkinen mitätön Lajittelu (T-kohteet) (int sortedRangeEnd \u003d 0; while (sortedRangeEnd< items.Length) { int nextIndex = FindIndexOfSmallestFromIndex(items, sortedRangeEnd); Swap(items, sortedRangeEnd, nextIndex); sortedRangeEnd++; } } private int FindIndexOfSmallestFromIndex(T items, int sortedRangeEnd) { T currentSmallest = items; int currentSmallestIndex = sortedRangeEnd; for (int i = sortedRangeEnd + 1; i < items.Length; i++) { if (currentSmallest.CompareTo(items[i]) > 0) (currentSmallest \u003d items [i]; currentSmallestIndex \u003d i;)) return currentSmallestIndex; )

Yhdistä lajittelu

Hajoita ja hallitse

Toistaiseksi olemme tarkastelleet lineaarisia algoritmeja. He käyttävät vähän ylimääräistä muistia, mutta niiden monimutkaisuus on toissijainen. Käyttämällä yhdistämislajittelua esimerkkinä tarkastelemme jakamis- ja valloitusalgoritmia. (jaa ja valloita).

Tämän tyyppiset algoritmit toimivat jakamalla suuri ongelma pienempiin, jotka on helpompi ratkaista. Käytämme niitä joka päivä. Esimerkiksi puhelinluettelon haku on yksi esimerkki tällaisesta algoritmista.

Jos haluat löytää henkilön Petrovin nimellä, et tee hakua aloittamalla kirjaimella A ja kääntämällä sivua kerrallaan. Voit todennäköisesti avata kirjan jonnekin keskelle. Jos pääset T-kirjaimeen, käännä muutama sivu taaksepäin, ehkä liian monta - O-kirjaimeen. Sitten siirryt eteenpäin. Täten, selatessasi edestakaisin vähemmän ja vähemmän sivuja, löydät lopulta haluamasi.

Kuinka tehokkaita nämä algoritmit ovat?

Oletetaan, että puhelinluettelossa on 1000 sivua. Jos avaat sen keskellä, hylkäät 500 sivua, joissa ei ole etsimääsi henkilöä. Jos et pääse oikealle sivulle, valitset oikean tai vasemman puolen ja jätät puolet käytettävissä olevista vaihtoehdoista. Nyt sinun on tarkasteltava 250 sivua. Siten jaamme tehtävämme uudelleen puoliksi ja voimme löytää henkilön puhelinluettelosta vain 10 näkymässä. Tämä edustaa 1% sivujen kokonaismäärästä, jota meidän on tarkasteltava lineaarisessa haussa.

Yhdistä lajittelu

Yhdistämislajittelussa jaetaan matriisi kahtia, kunnes jokainen osa on yhden elementin pituinen. Sitten nämä alueet palautetaan paikoilleen (yhdistetään) oikeassa järjestyksessä.

Katsotaanpa tällaista taulukkoa:

Jaetaan se puoliksi:

Jaamme jokaisen osan puoliksi, kunnes jäljellä on osia, joissa on yksi elementti:

Nyt kun olemme jakaneet matriisin mahdollisimman lyhyisiin osiin, yhdistämme ne oikeaan järjestykseen.

Ensinnäkin saamme ryhmät kahdesta lajitellusta elementistä, sitten "keräämme" ne neljän elementin ryhmiin ja lopuksi keräämme kaiken yhdessä lajiteltuun ryhmään.

Jotta algoritmi toimisi, meidän on toteutettava seuraavat toiminnot:

  1. Toiminto taulukon rekursiiviseen jakamiseen ryhmiin (Lajittelu-menetelmä).
  2. Yhdistäminen oikeassa järjestyksessä (Yhdistämistapa).

On syytä huomata, että toisin kuin lineaariset lajittelualgoritmit, yhdistävä lajittelu jakaa ja liimaa taulukon riippumatta siitä, onko se alun perin lajiteltu vai ei. Siksi siitä huolimatta, että pahimmassa tapauksessa se toimii nopeammin kuin lineaarinen, parhaimmillaan sen suorituskyky on heikompi kuin lineaarinen. Siksi yhdistäminen ei ole paras ratkaisu, kun sinun on lajiteltava osittain järjestetty taulukko.

Julkinen mitätön Lajittelu (T-kohteet) (jos (kohteet.Pituus<= 1) { return; } int leftSize = items.Length / 2; int rightSize = items.Length - leftSize; T left = new T; T right = new T; Array.Copy(items, 0, left, 0, leftSize); Array.Copy(items, leftSize, right, 0, rightSize); Sort(left); Sort(right); Merge(items, left, right); } private void Merge(T items, T left, T right) { int leftIndex = 0; int rightIndex = 0; int targetIndex = 0; int remaining = left.Length + right.Length; while(remaining > 0) (if (leftIndex\u003e \u003d left.Length) (items \u003d right;) else if (rightIndex\u003e \u003d right.Length) (items \u003d left;) else if (left.CompareTo (right))< 0) { items = left; } else { items = right; } targetIndex++; remaining--; } }

Nopea lajittelu

Quicksort on toinen jakamis- ja valloitusalgoritmi. Se toimii toistamalla rekursiivisesti seuraavat vaiheet:

  1. Valitse avainindeksi ja jaa taulukko kahteen osaan sen mukaan. Voit tehdä tämän monilla tavoilla, mutta tässä artikkelissa käytämme satunnaislukua.
  2. Siirrä kaikki avainta suuremmat elementit taulukon oikealle puolelle ja kaikki elementit vähemmän kuin avain vasemmalle. Avainelementti on nyt oikeassa asennossa - se on suurempi kuin mikä tahansa vasemmalla oleva elementti ja pienempi kuin mikä tahansa oikealla.
  3. Toista kaksi ensimmäistä vaihetta, kunnes taulukko on lajiteltu kokonaan.

Katsotaanpa, kuinka algoritmi toimii seuraavalla taulukolla:

Ensin valitaan satunnaisesti avainelementti:

Int pivotIndex \u003d _pivotRng.Next (vasen, oikea);

Nyt kun tiedämme avainindeksin (4), otamme arvon tähän indeksiin (6) ja siirrämme taulukon arvoja siten, että kaikki avainta suuremmat tai yhtä suuret luvut ovat oikealla puolella ja kaikki numerot vähemmän kuin avain on vasemmalla .... Huomaa, että avainelementin hakemisto voi muuttua siirtoprosessin aikana (näemme tämän pian).

Arvojen siirtäminen tapahtuu osiointimenetelmällä.

Tässä vaiheessa tiedämme, että arvo 6 on oikeassa paikassa. Toistamme tämän prosessin nyt taulukon oikealle ja vasemmalle puolelle.

Meillä on yksi lajittelematon arvo jäljellä, ja koska tiedämme, että kaikki muu on jo lajiteltu, algoritmi poistuu.

Satunnainen _pivotRng \u003d uusi satunnainen (); public void Lajittelu (T kohdetta) (quicksort (kohdetta, 0, kohdetta. pituus - 1);) private void quicksort (T kohdetta, int vasen, int oikea) (jos (vasen< right) { int pivotIndex = _pivotRng.Next(left, right); int newPivot = partition(items, left, right, pivotIndex); quicksort(items, left, newPivot - 1); quicksort(items, newPivot + 1, right); } } private int partition(T items, int left, int right, int pivotIndex) { T pivotValue = items; Swap(items, pivotIndex, right); int storeIndex = left; for (int i = left; i < right; i++) { if (items[i].CompareTo(pivotValue) < 0) { Swap(items, i, storeIndex); storeIndex += 1; } } Swap(items, storeIndex, right); return storeIndex; }

Johtopäätös

Tämä päättää aloittelijoille tarkoitettuja algoritmeja ja tietorakenteita käsittelevän artikkelisarjamme. Tänä aikana olemme käsittäneet linkitetyt luettelot, dynaamiset taulukot, binaariset hakupuut ja joukot esimerkkeillä C # -koodista.

Taulukoiden lajittelussa on kolme yleistä menetelmää:

  • Vaihto
  • Valinta (näytteenotto)
  • Lisää

Kuvittele korttipakkaus ymmärtämään näiden menetelmien toimintaa. Korttien lajitteleminen menetelmällä vaihto , aseta ne kuvapuoli ylöspäin pöydälle ja vaihda tilauskortit, kunnes koko pakkaus on kunnossa.

Menetelmässä valinta levitä kortit pöydälle, valitse vähiten tärkeä kortti ja laita se käteesi. Valitse sitten jäljellä olevista korteista uudelleen vähiten tärkeät kortit ja aseta se jo kädessä olevalle kortille. Prosessi toistetaan, kunnes kaikki kortit ovat kädessä; prosessin lopussa kansi lajitellaan.

Kansi lajitellaan menetelmällä terät , vedä kaikki kortit käteesi. Aseta ne yksi kerrallaan pöydälle ja aseta jokainen seuraava kortti oikeaan paikkaan. Kun kaikki kortit ovat pöydällä, pakkaus lajitellaan.

Lajittele inserttien mukaan

Lajittele inserttien mukaan - yksinkertainen lajittelualgoritmi. Vaikka tämä algoritmi on tehokkuudeltaan huonompi kuin monimutkaisemmat (kuten pikalajit), sillä on useita etuja:

· Vaikuttaa pieniin tietojoukoihin, jopa kymmeniä elementtejä voi olla paras;

· Tehokas jo osittain lajiteltuihin aineistoihin

· Se on vankka lajittelualgoritmi (ei muuta jo lajiteltujen elementtien järjestystä);

· Voi lajitella luettelon sellaisenaan;

Haittapuoli on algoritmin suuri monimutkaisuus: O ( n²)

Yleensä pahimmissa tapauksissa lisäyslajittelu on yhtä huono kuin kupla- ja valintalajittelu, ja keskimäärin se on vain hieman parempi.

Kuvaus

Algoritmin jokaisessa vaiheessa valitaan yksi syötetiedoista ja lisätään se haluttuun kohtaan jo lajiteltuun luetteloon, kunnes syötetiedot on käytetty loppuun. Menetelmä seuraavan elementin valitsemiseksi alkuperäisestä taulukosta on mielivaltainen; melkein mitä tahansa valintaalgoritmia voidaan käyttää. Yleensä (ja vankan lajittelualgoritmin saamiseksi) elementit lisätään siinä järjestyksessä kuin ne esiintyvät syötetaulukossa.

Algoritmianalyysi

Algoritmin toteutusaika riippuu syötetiedoista: mitä suurempi sarja on lajiteltava, sitä kauemmin lajittelu kestää. Myös matriisin alkuperäinen järjestys vaikuttaa ajonaikaan. Joten paras tapa on lajiteltu taulukko ja pahimmassa tapauksessa vastakkaiseen järjestykseen järjestetty taulukko. Algoritmin aika monimutkaisuus tulodatan pahimmassa tapauksessa on θ (n²).

Java-toteutus

julkinen mitätöinti sortSort () (

varten (Solmu cur \u003d ensimmäinen. Seuraava; cur! \u003d tyhjä; cur \u003d cur.sext) (

Solmu n \u003d edellinen edellinen;

Object val \u003d käyräarvo;

varten (; n! \u003d tyhjä; n \u003d n.prev) (

jos (((Vertailukelpoinen) n.arvo) .vertaaTo (val) > 0) {

n.seuraava \u003d n. arvo;

} muu {

jos (n! \u003d tyhjä) {

n.seuraava arvo \u003d val;

} muu {

ensimmäinen.arvo \u003d val;

Se lajittelee ensin kaksi ensimmäistä kohdetta. Sitten algoritmi lisää kolmannen elementin oikeaan sijaintiin kahden ensimmäisen elementin suhteen. Sen jälkeen se lisää neljännen kohteen kolmen kohteen luetteloon. Tätä prosessia toistetaan, kunnes kaikki elementit on lisätty. esimerkiksi, lajitellessasi taulukkoa dcab kukin algoritmin läpikulku näyttää tältä:

alkaa d c a b

Pass 1 c d a b

Pass 2 a c d b

Pass 3 a b c d

Valintalaji

Kuvaus

Kun lajitellaan, matriisista valitaan elementti, jolla on pienin arvo, ja se vaihdetaan ensimmäisen elementin kanssa. Sitten muusta n - 1 elementti, elementti, jolla on pienin avain, valitaan uudelleen ja vaihdetaan toisen elementin kanssa jne. Nämä vaihdot jatkuvat kahteen viimeiseen elementtiin asti. esimerkiksijos käytät valintamenetelmää taulukossa dcab, jokainen passi näyttää tältä:

Aloita d c a b Pass 1 a c d b Pass 2 a b d c Pass 3 a b c d

Analyysi

Valitettavasti, kuten kuplalajittelun yhteydessä, ulkosilmukka suoritetaan n - 1 kerta ja sisäinen - keskimäärin n/2 kertaa. Siksi lajittelu valinnan mukaan vaatii 1/2(n 2 -n) vertailut. Joten tämä on tilausalgoritmi n 2, mikä tekee liian hitaasta suuren määrän tuotteiden lajittelun. Vaikka kuplalajittelun ja valintalajittelun vertailumäärä on sama, jälkimmäisessä vaihtojen lukumäärä on keskimäärin paljon pienempi kuin kuplalajittelussa.

Java-toteutus

julkinen mitätöinti Valitse lajittelu () (

varten (Solmu a \u003d ensimmäinen; a! \u003d Viimeinen; a \u003d a. Seuraava) (

Solmu min \u003d viimeinen;

varten (Solmu b \u003d a; b! \u003d Viimeinen; b \u003d b. Seuraava) (

jos (((Vertailukelpoinen) b.val) .compareTo (min.val) < 0) {

a.val \u003d min.val;

Lajittele vaihdon mukaan

Tunnetuin algoritmi on kupla lajittelu... Sen suosio johtuu sen mielenkiintoisesta nimestä ja algoritmin yksinkertaisuudesta. Yleensä se on kuitenkin yksi pahimmista lajittelualgoritmeista.

Bubble sort kuuluu vaihtolajeihin, ts. lajitteluluokkaan vaihtomenetelmällä. Sen algoritmi sisältää toistuvia vertailuja (eli samojen elementtien useita vertailuja) ja tarvittaessa vierekkäisten elementtien vaihtoa. Elementit käyttäytyvät kuin ilmakuplat vedessä - jokainen nousee omalle tasolleen.

Havainnollistaaksemme, miten kuplalajittelu toimii, sanotaan, että alkuperäinen taulukko sisältää elementtejä dcab... Alla on taulukon tila jokaisen passin jälkeen:

alkaa d c a b

Pass 1 a d c b

Pass 2 a b d c

Pass 3 a b c d

Lajittelualgoritmia analysoitaessa on hyödyllistä tietää, kuinka monta vertailu- ja vaihtotoimintoa suoritetaan parhaimmissa, keskimääräisissä ja pahimmissa tapauksissa. Koska suoritettavan koodin ominaisuudet riippuvat tekijöistä, kuten kääntäjän suorittamista optimoinneista, prosessorien välisistä eroista ja toteutuksen yksityiskohdista, emme yritä saada näiden parametrien tarkkoja arvoja. Sen sijaan keskitymme kunkin algoritmin yleiseen suorituskykyyn.

Kuplalajittelussa vertailumäärä on aina sama, koska silmukoiden kaksi toistavat määritetyn määrän kertoja riippumatta siitä, onko luettelo alun perin tilattu vai ei. Tämä tarkoittaa, että kuplalajittelualgoritmi toimii aina

(n 2 -n)/2

vertailut missä n - lajiteltavien kohteiden lukumäärä. Tämä kaava on johdettu sen perusteella, että ulompi silmukka suoritetaan n - 1 kerta, ja sisäinen suoritetaan keskimäärin n/2 kertaa. Näiden määrien tulo antaa edellisen lausekkeen.

Kiinnitä huomiota jäseneen n 2 kaavassa. Kuplalajikkeen sanotaan olevan järjestysalgoritmi n 2, koska sen suoritusaika on verrannollinen lajiteltavien elementtien lukumäärän neliöön. On myönnettävä, että tilausalgoritmi n 2 ei ole tehokas suurelle määrälle kohteita, koska suoritusaika kasvaa eksponentiaalisesti lajiteltavien kohteiden määrän kanssa.

Kuplalajittelualgoritmissa vaihtojen määrä on parhaimmillaan nolla, jos taulukko on jo lajiteltu. Keskimääräisissä ja pahimmissa tapauksissa vaihdon määrä on kuitenkin myös noin luokkaa n 2 .


Samankaltaisia \u200b\u200btietoja.