Naturlig fusionsalgoritme c. Flet sortering gjort enkelt

Det er blevet anslået, at op til en fjerdedel af tiden på centraliserede computere bruges på at sortere data. Dette skyldes, at det er meget nemmere at finde en værdi i et array, der er forhåndssorteret. Ellers er søgen lidt som at lede efter en nål i en høstak.

Der er programmører, der gør alt arbejdstid udføres i undersøgelse og implementering af sorteringsalgoritmer. Dette skyldes, at langt størstedelen af ​​forretningssoftware involverer databasestyring. Folk søger hele tiden i databaser efter information. Det betyder, at søgealgoritmer er meget efterspurgte.

Men der er et "men". Søgealgoritmer arbejde meget hurtigere med databaser, der allerede er sorteret. I dette tilfælde kræves kun lineær søgning.

Mens computerne er uden brugere på nogle tidspunkter, fortsætter sorteringsalgoritmerne med at fungere på databaserne. Søgere kommer igen, og databasen er allerede sorteret ud fra et eller andet søgeformål.

Denne artikel giver eksempler på implementeringer af standardsorteringsalgoritmer.

Udvælgelsessortering

For at sortere et array i stigende rækkefølge, skal du ved hver iteration finde elementet med højeste værdi. Med det skal du bytte det sidste element. Det næste element med den højeste værdi placeres på næstsidste plads. Dette bør ske, indtil elementerne på de første steder i arrayet er i den rigtige rækkefølge.

C++ kode

void SortAlgo::selectionSort(int data, int lenD) ( int j = 0; int tmp = 0; for (int i=0; i data[k])( j = k; ) ) tmp = data[i]; data[i] = data[j]; data[j] = tmp; ))

Boble sortering

Boblesortering sammenligner tilstødende elementer og bytter plads, hvis det næste element er mindre end det forrige. Der kræves flere gennemløb af data. Under den første gennemgang sammenlignes de to første elementer i arrayet. Hvis de ikke er i orden, byttes de, og derefter sammenlignes elementerne i det næste par. Under samme betingelse skifter de også plads. Sortering sker således i hver cyklus, indtil slutningen af ​​arrayet nås.

C++ kode

void SortAlgo::bubbleSort(int data, int lenD) ( int tmp = 0; for (int i = 0;i =(i+1);j--)( if (data[j]

Indsættelsessortering

Indsættelsessortering opdeler arrayet i to områder: ordnet og uordnet. Til at begynde med er hele arrayet et uordnet område. Ved den første passage fjernes det første element fra det uordnede område og placeres i den korrekte position i det ordnede område.

Ved hver passage øges størrelsen af ​​den ordnede region med 1, og størrelsen af ​​den uordnede region falder med 1.

Hovedsløjfen løber fra 1 til N-1. Ved den jth iteration indsættes element [i] i den korrekte position i det ordnede område. Dette gøres ved at flytte alle elementer i det ordnede område, der er større end [i] en position til højre. [i] indsættes i mellemrummet mellem de elementer, der er mindre end [i] og dem, der er større end [i].

C++ kode

void SortAlgo::insertionSort(int data, int lenD) ( int key = 0; int i = 0; for (int j = 1;j =0 && data[i]>nøgle)( data = data[i]; i = i-1; data=nøgle; ) ) )

Flet sortering

C++ kode

void SortAlgo::mergeSort(int data, int lenD) ( if (lenD>1)( int middle = lenD/2; int rem = lenD-middle; int * L = new int; int * R = new int; for ( int i=0;i

Hurtig sortering

Quicksort bruger en divider and conquer-algoritme. Det begynder med at opdele det originale array i to områder. Disse dele er til venstre og højre for det markerede element, kaldet støtten. Ved slutningen af ​​processen vil den ene del indeholde elementer, der er mindre end referencen, og den anden del vil indeholde elementer, der er større end referencen.

C++ kode

void SortAlgo::quickSort(int * data, int const len) ( int const lenD = len; int pivot = 0; int ind = lenD/2; int i,j = 0,k = 0; if (lenD>1) ( int * L = new int ; int * R = new int ; pivot = data; for (i=0;i

  • Algoritmer,
  • Programmering
  • Nogen sagde det engang

    ...enhver videnskabsmand, der ikke kunne forklare en otte-årig, hvad han lavede, var en charlatan.

    Det viser sig, at det var Kurt Vonnegut.

    Jeg søgte ikke at bevise denne erklæring. Jeg søgte at gendrive min dumhed.

    Lad os sige, at vi har to arrays af tal, sorteret i stigende rækkefølge.

    Int a1 = ny int (21, 23, 24, 40, 75, 76, 78, 77, 900, 2100, 2200, 2300, 2400, 2500); int a2 = ny int (10, 11, 41, 50, 65, 86, 98, 101, 190, 1100, 1200, 3000, 5000);
    Det er nødvendigt at flette dem til en ordnet matrix.

    Int a3 = ny int;
    Dette er en opgave til flettesortering.

    Hvad er det? Der er et svar på internettet, der er en beskrivelse af algoritmen, men jeg forstod det ikke på én gang og besluttede at finde ud af det selv. For at gøre dette skal du forstå grundprincippet i algoritmen, så du kan genskabe algoritmen fra hukommelsen i forhold til dit problem.

    Lad os starte for sundhed

    Lad os gå gradvist og bruge det, der er på overfladen: Vi tager et element fra hvert array et efter et, sammenligner dem og "fletter" dem til et array. Vi vil placere det mindre element først, det større element for det andet. Så efter den første omgang er alt i orden:

    10, 21
    Og efter anden omgang er det ikke så godt:

    10, 21, 11, 23
    Det er klart, at vi er nødt til at sammenligne elementerne med dem, der allerede er tilføjet.

    Lad os starte igen

    Lad os have en vis midlertidig buffer af elementer sammenlignet på hvert trin. Efter det første gennemløb vil det indeholde 21 og 10. Efter sammenligningen vil vi flytte det mindre element 10 fra bufferen til det resulterende array og forlade det større element 21, fordi vi ikke ved, hvad der vil være bag det.

    Efter det andet gennemløb vil bufferen indeholde 21, 23 og 11. Det er ikke klart, hvad du skal gøre med dem, du kan sammenligne mere end to elementer, men det er ikke så nemt.

    Lad os så blive enige om, at vi tager et element fra hvert array ind i denne buffer. Da det er nemmere at sammenligne to elementer med hinanden, og generelt har vi to entiteter - to arrays. Så efter det andet gennemløb vil der være 21 og 11 i bufferen, fordi "repræsentanten" for det første array allerede er i bufferen - det er 21. Vi sammenligner dem og sender det mindre til det resulterende array. Så efter det andet gennemløb vil vi have i det resulterende array:

    10, 11
    Og i bufferen - 21.

    Ved den tredje passage tager vi 41 fra det andet array ind i bufferen, fordi "repræsentanten" for det første array forbliver i bufferen. Vi sammenligner 21 og 41 og fjerner til sidst 21 fra bufferen.

    Efter det tredje pas vil vi have i det resulterende array:

    10, 11, 21
    På det fjerde pas vil vi sammenligne to værdier fra bufferen - 41 og 23. Det resulterende array vil indeholde:

    10, 11, 21, 23
    Det vil sige, først nu - på det fjerde og ikke på det andet pas - viste resultatet sig at være korrekt. Det viser sig, at du i en løkke skal huske det aktuelle indeks for hvert array, og selve løkken kan være lige så lang som summen af ​​arrayernes længder.

    Vi nærmer os slutningen, men pludselig

    Hvad vil vi gøre, når det resulterende array består af:

    10, 11, 21, 23, 24, 40, 41, 50, 65, 75, 76, 78, 77, 86, 98, 101, 190, 900, 1100, 1200, 2100, 2200, 2300, 2400, 2500,
    Vil bufferen indeholde 3000 fra det andet array, og vil alle elementer løbe ud i det første? Da vores arrays er sorteret, tager vi blot 3000 fra bufferen og de resterende 5000. Det vil sige, at vi skal tjekke for hvert indeks for at se, om vi har overskredet antallet af elementer i hver af arrays.

    Lad os komplicere opgaven

    Hvad hvis vi har usorterede arrays? Normalt handler opgaven om at sortere ét array. Så kan merge sort også bruges.

    Lad det første array (f.eks. tage flere elementer fra det) have følgende arrangement af elementer:

    2100, 23, 40, 24, 2, 1.
    Vi vil sortere det. Da det er nemmere at sammenligne to elementer ad gangen, lad os dele arrayet ligeligt op i to:

    2150, 23, 40
    Og
    24, 2, 1.
    Du får tre elementer. En masse! Lad os opdele hvert array ligeligt, vi får fire arrays:

    2100, 23 40 24, 2 1
    Lad os nu sortere hvert af arrays ved blot at sammenligne det første og andet element (hvor de findes):

    23, 2100 40 2, 24 1
    Og vi vil flette det tilbage i henhold til den tidligere algoritme - gennem en buffer. Efter den første fletning får vi to arrays:

    23, 40, 2100 1, 2, 24
    Og vi smelter sammen igen - til én matrix:

    1, 2, 23, 24, 40, 2100
    Dette er, hvordan vi flette sorterede arrayet.

    Bundlinie

    Merge sort involverer således at dele arrayet ligeligt, indtil et array producerer flere små - ikke mere end to elementer i størrelse. De to elementer kan let sammenlignes med hinanden og arrangeres afhængigt af kravet: stigende eller faldende.

    Efter opdelingen følger en omvendt sammenfletning, hvor et element fra hvert array på et tidspunkt (eller pr. gennemløb gennem løkken) udvælges og sammenlignes med hinanden. Det mindste (eller største) element sendes til det resulterende array, det resterende element forbliver relevant til sammenligning med et element fra et andet array i næste trin.

    Lad os udtrykke det i kode (Java)

    Et eksempel på sortering i stigende rækkefølge af to sorterede arrays:

    Int a1 = ny int (21, 23, 24, 40, 75, 76, 78, 77, 900, 2100, 2200, 2300, 2400, 2500); int a2 = ny int (10, 11, 41, 50, 65, 86, 98, 101, 190, 1100, 1200, 3000, 5000); int a3 = ny int; int i=0, j=0; for (int k=0; k a1.længde-1) ( int a = a2[j]; a3[k] = a; j++; ) else if (j > a2.længde-1) ( int a = a1[i]; a3[k] = a; i++ ) else if (a1[i]< a2[j]) { int a = a1[i]; a3[k] = a; i++; } else { int b = a2[j]; a3[k] = b; j++; } }
    Her:

    A1 og a2 - arrays, der skal flettes;
    a3 - resulterende array;
    i og j er indekser for arrays henholdsvis a1 og a2, som peger på de aktuelle elementer ved hvert trin og danner den samme buffer.

    De to første betingelser kontrollerer, at indekserne ikke går ud over antallet af elementer i arrays. Den tredje og fjerde betingelse sikrer, at det mindste element fra henholdsvis det første og det andet array flyttes ind i arrayet.

    Flet sorteringsfunktion

    Lad os formatere ovenstående kode som en rekursiv funktion, der adskiller arrays så længe som muligt, med parametre, der svarer til hele arrayet på det første kald, dets halvdele på det andet og tredje kald osv.

    Privat void SortUnsorted(int a, int lo, int hi) ( if (hej<= lo) return; int mid = lo + (hi - lo) / 2; SortUnsorted(a, lo, mid); SortUnsorted(a, mid + 1, hi); int buf = Arrays.copyOf(a, a.length); for (int k = lo; k <= hi; k++) buf[k] = a[k]; int i = lo, j = mid + 1; for (int k = lo; k <= hi; k++) { if (i >mid) ( a[k] = buf[j]; j++; ) else if (j > hi) ( a[k] = buf[i]; i++; ) else if (buf[j]< buf[i]) { a[k] = buf[j]; j++; } else { a[k] = buf[i]; i++; } } }
    Her:

    A – array;
    lo – positionen af ​​det første element i arrayet (for den første iteration = 0);
    hi – positionen af ​​det sidste element i arrayet (for den første iteration = a.length - 1).

    For at forenkle koden og forbedre læsbarheden introducerer vi Swap-metoden, som vil bytte værdier i arrayet efter indeks.

    Void Swap(T items, int left, int right) ( if (venstre != højre) ( T temp = items; items = items; items = temp; ) )

    Boble sortering

    Boblesortering er den enkleste sorteringsalgoritme. Den går gennem arrayet flere gange, og ved hvert trin flyttes den største usorterede værdi til slutningen af ​​arrayet.

    For eksempel har vi en matrix af heltal:

    Første gang vi passerer gennem arrayet, sammenligner vi værdierne 3 og 7. Da 7 er større end 3, lader vi dem være som de er. Så sammenligner vi 7 og 4. 4 er mindre end 7, så vi bytter dem og flytter de syv en position tættere på enden af ​​arrayet. Nu ser det sådan ud:

    Denne proces gentages, indtil de syv når næsten slutningen af ​​arrayet. Til sidst sammenlignes det med element 8, som er større, hvilket betyder, at der ikke sker nogen udveksling. Efter at vi har krydset arrayet én gang, ser det sådan ud:

    Da der er foretaget mindst én værdiudveksling, er vi nødt til at gå gennem arrayet igen. Som et resultat af dette pas flytter vi tallet 6 på plads.

    Og igen blev der foretaget mindst én udveksling, hvilket betyder, at vi går gennem arrayet igen.

    Ved næste gennemløb foretages der ingen udveksling, hvilket betyder, at vores array er sorteret, og algoritmen har afsluttet sit arbejde.

    Offentlig void Sort(T elementer) ( bool byttet; do ( byttet = falsk; for (int i = 1; i)< items.Length; i++) { if (items.CompareTo(items[i]) >0) ( Swap(elementer, i - 1, i); byttet = sand; ) ) ) while (byttet != falsk); )

    Indsættelsessortering

    Indsættelsessortering fungerer ved at iterere gennem et array og flytte den ønskede værdi til begyndelsen af ​​arrayet. Efter at den næste position er behandlet, ved vi, at alle positioner før den er sorteret, men ikke efter den.

    Et vigtigt punkt: indsættelsessortering behandler matrixelementer i rækkefølge. Da algoritmen itererer gennem elementer fra venstre mod højre, ved vi, at alt til venstre for det aktuelle indeks allerede er sorteret. Denne figur viser, hvordan den sorterede del af arrayet vokser for hver gang:

    Gradvist vokser den sorterede del af arrayet, og til sidst vil arrayet blive ordnet.

    Lad os se på et specifikt eksempel. Her er vores usorterede array, vi skal bruge:

    Algoritmen starter ved indeks 0 og værdi 3. Da dette er det første indeks, anses arrayet til og med det som sorteret.

    På dette trin sorteres elementer med indeks 0..1, men der vides intet om elementer med indeks 2..n.

    Værdien 4 markeres derefter Da den er mindre end syv, skal vi flytte den til den korrekte position i den sorterede del af arrayet. Tilbage står spørgsmålet: hvordan defineres det? Dette gøres ved hjælp af FindInsertionIndex-metoden. Den sammenligner værdien (4), der er sendt til den, med hver værdi i den sorterede del, indtil den finder et sted at indsætte.

    Så vi fandt indeks 1 (mellem værdier 3 og 7). Indsæt-metoden udfører en indsættelse ved at fjerne den indsatte værdi fra arrayet og flytte alle værdier, startende ved indsætningsindekset, til højre. Nu ser arrayet således ud:

    Nu er den del af arrayet, der starter fra element nul og slutter med element med indeks 2, sorteret. Det næste gennemløb starter ved indeks 3 og værdi 4. Efterhånden som algoritmen fungerer, fortsætter vi med at lave sådanne indsættelser.

    Når der ikke er flere indsættelser tilgængelige, betragtes arrayet som fuldstændigt sorteret, og algoritmen er færdig.

    Offentlig void Sort(T elementer) ( int sortedRangeEndIndex = 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) ( return index; ) ) throw new InvalidOperationException("Indsættelsesindekset blev ikke fundet"); ) private void Insert(T itemArray, int indexInsertingAt, int indexInsertingFrom) ( // itemArray = 0 1 2 4 5 6 3 7 // insertingAt = 3 // insertingFrom = 6 // // Handlinger: // 1: Gem den aktuelle indeks i temp // 2: Erstat indexInsertingAt med indexInsertingFrom // 3: Erstat indexInsertingAt med indexInsertingFrom ved position +1 // Skift elementer tilbage med én // 4: Skriv temp ved position i array + 1. // Trin 1. T temp = itemArray; // Trin 2. itemArray = itemArray; // Trin 3. for (int current = indexInsertingFrom; current > indexInsertingAt; current--) ( itemArray = itemArray; ) // Trin 4. itemArray = temp;

    Sortering efter valg

    Udvælgelsessortering er en hybrid mellem boblesortering og indsættelsessortering. Ligesom boblesortering går denne algoritme gennem arrayet igen og igen og flytter en værdi til den korrekte position. I modsætning til boblesortering vælger den dog den mindste usorterede værdi i stedet for den største. Som med indsættelsessortering er den ordnede del af arrayet placeret i begyndelsen, mens den i boblesortering er i slutningen.

    Lad os se på, hvordan udvælgelsessortering fungerer på vores usorterede array.

    Ved den første gennemgang bruger algoritmen FindIndexOfSmallestFromIndex-metoden til at finde den mindste værdi i arrayet og flytte den til begyndelsen.

    Med så lille et array kan vi med det samme se, at den mindste værdi er 3, og den er allerede i den rigtige position. På dette stadium ved vi, at den første position i arrayet (indeks 0) er den mindste værdi, derfor er begyndelsen af ​​arrayet allerede sorteret. Så vi starter en anden omgang - denne gang ved at bruge indeks fra 1 til n - 1.

    Ved det andet gennemløb bestemmer vi, at den mindste værdi er 4. Vi bytter den med det andet element, syv, hvorefter 4 placeres i sin rigtige position.

    Nu starter den usorterede del af arrayet ved indeks 2. Det vokser med et element for hver gang algoritmen passerer. Hvis vi ikke har foretaget en eneste udveksling på et hvilket som helst tidspunkt, betyder det, at arrayet er sorteret.

    Efter yderligere to gennemløb fuldfører algoritmen sit arbejde:

    Offentlig void Sort(T elementer) ( int sortedRangeEnd = 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 = items[i]; currentSmallestIndex = i; ) ) returner aktuelleSmallestIndex; )

    Flet sortering

    Del og hersk

    Indtil videre har vi set på lineære algoritmer. De bruger lidt ekstra hukommelse, men har kvadratisk kompleksitet. Ved at bruge flettesortering som et eksempel, ser vi på en del-og-hersk-algoritme. (del og hersk).

    Denne type algoritme virker ved at opdele et stort problem i mindre, nemmere at løse. Vi bruger dem hver dag. For eksempel er søgning i telefonbogen et eksempel på en sådan algoritme.

    Hvis du vil finde en person, der hedder Petrov, vil du ikke søge, der starter med bogstavet A og vender en side ad gangen. Du vil højst sandsynligt åbne bogen et sted i midten. Hvis du trykker på T'et, vil du bladre et par sider tilbage, måske for mange til O'et. Så går du fremad. Ved at bladre frem og tilbage gennem færre og færre sider, vil du således til sidst finde den, du skal bruge.

    Hvor effektive er disse algoritmer?

    Lad os sige, at der er 1000 sider i telefonbogen. Hvis du åbner den halvvejs, smider du 500 sider, der ikke indeholder den person, du leder efter. Hvis du ikke kommer til den rigtige side, vælger du højre eller venstre side og står igen tilbage med halvdelen af ​​de tilgængelige muligheder. Nu har du 250 sider at se igennem. På denne måde deler vi vores problem i to igen og igen og kan finde en person i telefonbogen på kun 10 blik. Dette repræsenterer 1 % af det samlede antal sider, som vi skal kigge igennem i en lineær søgning.

    Flet sortering

    Ved flettesortering deler vi arrayet i to, indtil hver sektion er et element langt. Derefter returneres disse sektioner til deres plads (fusioneret) i den rigtige rækkefølge.

    Lad os se på et array som dette:

    Lad os dele det i to:

    Og vi deler hver del i to, indtil der er dele med ét element tilbage:

    Nu hvor vi har opdelt arrayet i de kortest mulige sektioner, slår vi dem sammen i den rigtige rækkefølge.

    Først får vi grupper af to sorterede elementer, derefter "samler" vi dem i grupper af fire elementer, og til sidst samler vi alt sammen i et sorteret array.

    For at algoritmen skal fungere, skal vi implementere følgende operationer:

    1. En operation til rekursiv opdeling af et array i grupper (Sorteringsmetode).
    2. Fletning i den rigtige rækkefølge (Merge-metoden).

    Det er værd at bemærke, at i modsætning til lineære sorteringsalgoritmer vil merge sort opdele og flette arrayet, uanset om det oprindeligt blev sorteret eller ej. Derfor, selvom det i værste tilfælde vil præstere hurtigere end lineært, vil det i bedste tilfælde være lavere end lineært. Derfor er merge sort ikke den bedste løsning, når du skal sortere et delvist ordnet array.

    Offentlig ugyldig Sortering(T elementer) ( if (elementer.Længde<= 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 >= left.Length) ( items = right; ) else if (rightIndex >= right.Length) ( items = left; ) else if (left.CompareTo(right)< 0) { items = left; } else { items = right; } targetIndex++; remaining--; } }

    Hurtig sortering

    Quicksort er en anden opdel-og-hersk-algoritme. Det fungerer ved rekursivt at gentage følgende trin:

    1. Vælg et nøgleindeks og opdel arrayet i to dele ved hjælp af det. Dette kan gøres på mange måder, men i denne artikel bruger vi et tilfældigt tal.
    2. Flyt alle elementer større end nøglen til højre side af arrayet, og alle elementer mindre end nøglen til venstre. Nøgleelementet er nu i den rigtige position - det er større end ethvert element til venstre og mindre end noget element til højre.
    3. Vi gentager de første to trin, indtil arrayet er helt sorteret.

    Lad os se på algoritmen i aktion på følgende array:

    Først vælger vi tilfældigt et nøgleelement:

    Int pivotIndex = _pivotRng.Next(venstre, højre);

    Nu hvor vi kender nøgleindekset (4), tager vi værdien placeret ved det indeks (6) og flytter værdierne i arrayet, så alle tal større end eller lig med nøglen er på højre side, og alle numre mindre end tasten er til venstre. Bemærk, at indekset for nøgleelementet kan ændre sig under processen med at overføre værdier (vi vil se dette snart).

    Flytning af værdier udføres ved hjælp af partitionsmetoden.

    På dette tidspunkt ved vi, at værdien 6 er i den rigtige position. Nu gentager vi denne proces for højre og venstre side af arrayet.

    Vi står tilbage med én usorteret værdi, og da vi ved, at alt andet allerede er sorteret, afsluttes algoritmen.

    Random _pivotRng = new Random(); public void Sort(T items) ( quicksort(items, 0, items.Length - 1); ) private void quicksort(T items, int left, int right) ( if (venstre)< 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; }

    Konklusion

    Dette afslutter vores serie af artikler om algoritmer og datastrukturer for begyndere. I løbet af denne tid dækkede vi linkede lister, dynamiske arrays, binære søgetræer og sæt med kodeeksempler i C#.

    Algoritme flette sortering blev foreslået af forfaderen til moderne computere, John von Neumann. Selve metoden er stabil, dvs. den ændrer ikke elementer af samme værdi i listen.

    Merge sort er baseret på princippet om adskille og hersk. Listen er opdelt i lige store eller næsten lige store dele, som hver er sorteret separat. Hvorefter de allerede bestilte dele smelter sammen. Denne proces kan beskrives i nogle detaljer som følger:

    1. arrayet er rekursivt delt i to, og hver halvdel deles, indtil størrelsen af ​​den næste underarray bliver lig med én;

    2. Dernæst udføres en algoritmeoperation kaldet fletning. To enhedsarrays flettes sammen til et fælles resulterende array, og det mindre element vælges fra hver (sorteret i stigende rækkefølge) og skrives til den frie venstre celle i det resulterende array. Derefter samles et tredje fælles sorteret array fra de to resulterende arrays og så videre. Hvis et af arrays løber tør, tilføjes elementerne i det andet til det samlede array;

    3. i slutningen af ​​fletteoperationen omskrives elementer fra det resulterende array til det originale.

    Subrutine MergeSort opdeler og sorterer arrayet rekursivt, og Fusionere er ansvarlig for dets sammensmeltning. Sådan kan du skrive pseudokoden for hovedunderrutinen:

    Subrutine MergeSort(EN, først, sidst)

    EN- række

    først, sidst– numre på henholdsvis det første og det sidste element

    Hvis først<sidst At

    Opkald MergeSort(EN, først, (først+sidst)/2) //sortering i venstre side

    Opkald MergeSort(EN, (først+sidst)/2+1, sidst) //sortering i højre side

    Opkald Fusionere(EN, først, sidst) //sammenlægning af to dele

    Denne underrutine udføres kun, hvis nummeret på det første element er mindre end nummeret på det sidste. Som allerede nævnt, fra subrutinen MergeSort subrutine kaldes Fusionere, som udfører flettehandlingen. Lad os gå videre til at overveje sidstnævnte.

    Job Fusionere består i at danne et ordnet resulterende array ved at flette to også sorterede arrays af mindre størrelser. Her er pseudokoden for denne rutine:

    Subrutine Fusionere(EN, først, sidst)

    Start, endelig– numre på de første elementer i venstre og højre del

    mas- række, midten- gemmer nummeret på det midterste element

    midten=(først+sidste)/2 //beregning af det midterste element

    Start=først//begyndelsen af ​​venstre side

    endelig=midten+1 //begyndelsen af ​​højre side

    Cyklus j=først Før sidst execute //execute fra start til slut

    Hvis (( Start<=midten) Og (( endelig>sidst) eller ( EN[Start]<EN[endelig]))) At

    mas[j]=EN[Start]

    øge Start inden 1


    mas[j]=EN[endelig]

    øge endelig inden 1

    Cyklus j=først Før sidst udfør //retur resultatet til listen

    EN[j]=mas[j]

    Lad os analysere flettesorteringsalgoritmen ved hjælp af følgende eksempel (fig. 6.10). Der er en uordnet række af tal: 2, 6, 7, 1, 3, 5, 0, 4. Efter at have opdelt denne rækkefølge i enhedsarrays, vil so(stigende) se sådan ud:

    Figur 6.10 – Eksempel på flettesortering

    Arrayet blev opdelt i enkelte arrays, som algoritmen smelter sammen i par, indtil der opnås et enkelt array, hvor alle elementer er i deres positioner.

    Programkode i C++:

    void Merge(int *A, int først, int sidst) //funktion, der slår arrays sammen

    int midt, start, endelig, j;

    int *mas=ny int;

    midt=(første+sidste)/2; //beregn det midterste element

    start=først; //begyndelsen af ​​venstre side

    slut=midt+1; //begyndelsen af ​​højre side

    for(j=først; j<=last; j++) //выполнять от начала до конца

    hvis ((start<=middle) && ((final>sidste) || (EN

    mas[j]=A;

    mas[j]=A;

    for (j=først; j<=last; j++) A[j]=mas[j]; //возвращение результата в список

    void MergeSort(int *A, int first, int last) //rekursiv sorteringsprocedure

    hvis (først

    MergeSort(A, første, (første+sidste)/2); //sortering i venstre side

    MergeSort(A, (først+sidste)/2+1, sidste); //sortering i højre side

    Merge(A, first, last); //sammenlægning af to dele

    void main() //hovedfunktion

    cout<<"Размер массива >";cin>>n;

    for (i=1; i<=n; i++)

    cout< ";

    MergeSort(A, 1, n); //kald sorteringsproceduren

    cout<<"Упорядоченный массив: "; //вывод упорядоченного массива

    for (i=1; i<=n; i++) cout<

    Programkode i Pascal:

    type array=array af heltal;

    var n, i: heltal;

    procedure Merge(var A: massiv; første, sidste: heltal); (procedure, der slår arrays sammen)

    var middle, start, final, j: heltal;

    midt:=(første+sidste) div 2; (beregning af det midterste element)

    start:=først; (begyndelsen af ​​venstre side)

    endelig:=midt+1; (begyndelsen af ​​højre side)

    for j:=første til sidste gør (udfør fra start til slut)

    hvis (start<=middle) and ((final>sidste) eller (A

    mas[j]:=A;

    mas[j]:=A;

    for j:=først til sidst gør A[j]:=mas[j]; (returnerer resultatet til en matrix)

    procedure MergeSort(var A: massiv; først, sidste: heltal); (rekursiv sorteringsprocedure)

    hvis først

    MergeSort(A, første, (første+sidste) div 2); (sortér venstre side)

    MergeSort(A, (første+sidste) div 2+1, sidste); (sortering i højre side)

    Merge(A, first, last); (sammenlægning af to dele)

    start (hovedblok af programmet)

    write("Array størrelse > ");

    for i:=1 til n gør

    skriv(i, " element > ");

    MergeSort(A, 1, n); (kalder sorteringsproceduren)

    write("Ordret array: "); (sorteret array output)

    for i:=1 til n skal du skrive(A[i], " ");

    Ulempen ved merge sort er, at den bruger ekstra hukommelse. Men når du skal arbejde med filer eller lister, der kun tilgås sekventielt, så er det meget praktisk at bruge denne særlige metode. Fordelene ved algoritmen inkluderer også dens stabilitet og gode driftshastighed. O(n*log n).