logo

Spoji sortiraj u Pythonu

Sortiranje spajanjem slično je algoritmu brzog sortiranja jer radi na konceptu podijeli pa vladaj. To je jedan od najpopularnijih i najučinkovitijih algoritama za sortiranje. To je najbolji primjer za kategoriju algoritama podijeli pa vladaj.

Dijeli zadanu listu na dvije polovice, poziva sebe za dvije polovice i zatim spaja dvije sortirane polovice. Mi definiramo sjediniti() funkcija koja se koristi za spajanje dviju polovica.

Podliste se uvijek iznova dijele na polovice dok ne dobijemo samo jedan element. Zatim kombiniramo par popisa jednog elementa u dva popisa elemenata, sortirajući ih u procesu. Dva sortirana para elemenata se spajaju u četiri liste elemenata, i tako dalje dok ne dobijemo sortiranu listu.

Koncept sortiranja spajanjem

Pogledajmo sljedeći dijagram sortiranja spajanjem.

Dati popis podijelili smo u dvije polovice. Popis se ne može podijeliti na jednake dijelove, to uopće nije važno.

Sortiranje spajanjem može se implementirati na dva načina - pristupom odozgo prema dolje i pristupom odozdo prema gore. Koristimo pristup odozgo prema dolje u gornjem primjeru, što je sortiranje spajanjem koje se najčešće koristi.

Pristup odozdo prema gore pruža veću optimizaciju koju ćemo definirati kasnije.

Glavni dio algoritma je način na koji kombiniramo dvije sortirane podliste. Spojimo dvije sortirane liste za spajanje.

  • A : [ 2 , 4, 7, 8]
  • B : [ 1 , 3, 11]
  • sortirano : prazno

Prvo promatramo prvi element obje liste. Nalazimo da je prvi element B manji, pa ga dodajemo u našu sortiranu listu i krećemo se naprijed na B listi.

  • A : [ 2 , 4, 7, 8]
  • B : [1, 3 , jedanaest]
  • Poredano: 1

Sada gledamo sljedeći par elemenata 2 i 3. 2 je manji pa ga dodajemo u našu sortiranu listu i idemo naprijed prema listi.

  • A : [ 2 , 4, 7, 8]
  • B : [1, 3 , jedanaest]
  • Poredano: 1

Nastavite s ovim postupkom i završit ćemo s sortiranim popisom {1, 2, 3, 4, 7, 8, 11}. Mogu postojati dva posebna slučaja.

veličine lateks slova

Što ako oba podpopisa imaju iste elemente - U tom slučaju možemo premjestiti bilo koji podpopis i dodati element na sortirani popis. Tehnički, možemo se pomaknuti naprijed na oba podpopisa i dodati elemente na sortirani popis.

Nemamo više nijedan element u jednoj podlisti. Kada nam ponestane na podpopis jednostavno dodajte element drugog jedan za drugim.

Trebamo zapamtiti da elemente možemo sortirati bilo kojim redoslijedom. Dani popis sortiramo uzlaznim redoslijedom, ali lako možemo sortirati i silaznim redoslijedom.

Provedba

Algoritam sortiranja spajanjem implementiran je pristupom odozgo prema dolje. Može izgledati pomalo teško, pa ćemo razraditi svaki korak u detalje. Ovdje ćemo implementirati ovaj algoritam na dvije vrste kolekcija - popis cjelobrojnih elemenata (koji se obično koristi za uvođenje sortiranja) i prilagođeni objekt (praktičniji i realističniji scenarij).

Niz za sortiranje

Glavni koncept algoritma je podijeliti (pod)listu na polovice i sortirati ih rekurzivno. Nastavljamo s procesom sve dok ne dobijemo liste koje imaju samo jedan element. Razumimo sljedeću funkciju za dijeljenje -

 def merge_sort(array, left_index, right_index): if left_index >= right_index: return middle = (left_index + right_index)//2 merge_sort(array, left_index, middle) merge_sort(array, middle + 1, right_index) merge(array, left_index, right_index, middle) 

Naš primarni fokus je podijeliti popis na poddijelove prije sortiranja. Moramo dobiti cjelobrojnu vrijednost pa koristimo // operator za naše indekse.

Razumimo gornji postupak slijedeći korake.

  • Prvi korak je stvaranje kopija popisa. Prvi popis sadrži popise iz [lijevi_indeks,...,sredina] a drugi iz [srednji+1,?,desni_indeks] .
  • Pokazivačem prelazimo preko obje kopije popisa, odabiremo manju vrijednost od dvije vrijednosti i dodajemo ih na sortirani popis. Jednom kada dodamo element na popis i krećemo se naprijed u sortiranom popisu bez obzira.
  • Dodajte preostale elemente u drugoj kopiji sortiranom nizu.

Implementirajmo sortiranje spajanjem u Python programu.

Python program

 # Here, we are declaring the function to divide the lists in to the two sub lists # Here, we are passing the list1, left index, right index as the parameters def merge_sort(list1, left_index, right_index): if left_index &gt;= right_index: # here, we are checking the if condition return middle = (left_index + right_index)//2 # Here, we are finding the middle of the given two numbers merge_sort(list1, left_index, middle) # Here, we are calling the merge sort function till the middle number we got merge_sort(list1, middle + 1, right_index) # Here, we are calling the merge sort function till the end of the list i.e., right index merge(list1, left_index, right_index, middle) # Here, we are calling the merge function to merge the divided list using the merge # sort function above # Here, we are defining a function for merge the list after dividing def merge(list1, left_index, right_index, middle): # Here, we are creating subparts of a lists left_sublist = list1[left_index:middle + 1] right_sublist = list1[middle+1:right_index+1] # Here, we are initializing the values for variables that we use to keep # track of where we are in each list1 left_sublist_index = 0 right_sublist_index = 0 sorted_index = left_index # Here, we are traversing the both copies until we get run out one element while left_sublist_index <len(left_sublist) 1 and right_sublist_index < len(right_sublist): # here, we are declaring a while loop if our left_sublist has the smaller element, put it in sorted part then move forward (by increasing pointer) left_sublist[left_sublist_index] checking condition, is true will enter block list1[sorted_index]="left_sublist[left_sublist_index]" left_sublist_index="left_sublist_index" + otherwise add into right sublist else: moving sorted_index="sorted_index" go through remaining elements them len(left_sublist): len(right_sublist):# list1="[44," 65, 2, 3, 58, 14, 57, 23, 10, 1, 7, 74, 48] print('the given list before performing merge sort is: ', list1) this input unsorted array by user merge_sort(list1, 0, len(list1) -1) after is:', printing amd functions pre> <p> <strong>Output:</strong> </p> <pre> The given list before performing the merge sort is: [44, 65, 2, 3, 58, 14, 57, 23, 10, 1, 7, 74, 48] The given list after performing the merge sort is: [1, 2, 3, 7, 10, 14, 23, 44, 48, 57, 58, 65, 74] </pre> <h2>Sorting Custom Objects</h2> <p>We can also sort the custom objects by using the <a href="/python-tutorial-python-programming-language">Python</a> class. This algorithm is almost similar to the above but we need to make it more versatile and pass the comparison function.</p> <p>We will create a custom class, Car and add a few fields to it. We make few changes in the below algorithm to make it more versatile. We can do this by using the lambda functions.</p> <p>Let&apos;s understand the following example.</p> <h3>Python Program</h3> <pre> class Car: # here, we are declaring a class named car def __init__(self, make, model, year): self.make = make # Here, we are using the self to declare the make variables locally self.model = model # Here, we are using the self to declare the model variables locally self.year = year # Here, we are using the self to declare the year variables locally def __str__(self): return str.format(&apos;Make: {}, Model: {}, Year: {}&apos;, self.make, self.model, self.year) # Here, we are returning the format of the strings given def merge(list1, l, r, m, comp_fun): # Here, we are defining a function for merge the list using the compound function left_copy = list1[l:m + 1] # here, we are coping the left part of the list r_sublist = list1[m+1:r+1] # here, we are coping the right part of the list left_copy_index = 0 # here, we are coping the left part indexes of the list r_sublist_index = 0 # here, we are coping the right part indexes of the list sorted_index = l while left_copy_index <len(left_copy) 1 and r_sublist_index < len(r_sublist): # here, we are declaring a while loop using the comp_fun instead of simple comparison operator if comp_fun(left_copy[left_copy_index], r_sublist[r_sublist_index]): checking condition, it is true then will enter block list1[sorted_index]="left_copy[left_copy_index]" left_copy_index="left_copy_index" + else: condition false else sorted_index="sorted_index" len(left_copy): <len(r_sublist): def merge_sort(list1, l, r, comp_fun): merge sort function to given list l>= r: # Here, we are checking the if condition, if it is true then we will enter the block return m = (l + r)//2 # here, we are finding the middle element of the list merge_sort(list1, l, m, comp_fun) # Here, we are calling the merge sort function till the middle number we got merge_sort(list1, m + 1, r, comp_fun) # Here, we are calling the merge sort function from the middle number we got merge(list1, l, r, m, comp_fun) # Here, we are calling the merge function to merge the divided list using the merge # sort function above car1 = Car(&apos;Renault&apos;, &apos;33 Duster&apos;, 2001) car2 = Car(&apos;Maruti&apos;, &apos;Maruti Suzuki Dzire&apos;, 2015) car3 = Car(&apos;Tata motor&apos;, &apos;Jaguar&apos;, 2004) car4 = Car(&apos;Cadillac&apos;, &apos;Seville Sedan&apos;, 1995) list1 = [car1, car2, car3, car4] merge_sort(list1, 0, len(list1) -1, lambda carA, carB: carA.year <carb.year) print('cars sorted by year:') for car in list1: # here, we are declaring the loop to iterate through list1 print(car) printing all data of and list print() merge_sort(list1, 0, len(list1) -1, lambda cara, carb: cara.make < carb.make) make:') pre> <p> <strong>Output:</strong> </p> <pre> Cars sorted by year: Make: Cadillac, Model: Seville Sedan, Year: 1995 Make: Renault, Model: 33 Duster, Year: 2001 Make: Tata motor, Model: Jaguar, Year: 2004 Make: Maruti, Model: Maruti Suzuki Dzire, Year: 2015 Cars sorted by make: Make: Cadillac, Model: Seville Sedan, Year: 1995 Make: Maruti, Model: Maruti Suzuki Dzire, Year: 2015 Make: Renualt, Model: 33 Duster, Year: 2001 Make: Tata motor, Model: Jaguar, Year: 2004 </pre> <h2>Optimization</h2> <p>We can improve the performance of the merge sort algorithm. First let&apos;s understand the difference between the top-down and bottom-up merge sort. The bottom-up approach sorts the elements of adjacent lists iteratively where the top-down approach breaks down the lists into the two halves.</p> <p>The given list is [10, 4, 2, 12, 1, 3], instead of breaking it down into [10], [4], [2], [12], [1], [3] - we divide into the sub lists which may already sorted: [10, 4], [2], [1, 12], [3] and now are ready to sort them.</p> <p>Merge sort is inefficient algorithm in both time and space for the smaller sub lists. So, insertion sort is more efficient algorithm than the merge sort for the smaller sub lists.</p> <h2>Conclusion</h2> <p>Merge sort is popular and efficient algorithm. It is more efficient algorithm for the large lists. It does not depend on the any unfortunate decisions that lead to bad runtimes.</p> <p>There is one major demerit in the merge sort. It uses the additional memory that is used to store the temporary copies of lists before merging them. However Merge sort is widely used in the software. Its performance is fast and produces the excellent result.</p> <p>We have discussed the merge sort concept in brief and implement it both on simple integer list and on custom objects via a lambda function used for comparison.</p> <hr></carb.year)></len(left_copy)></pre></len(left_sublist)>

Razvrstavanje prilagođenih objekata

Također možemo sortirati prilagođene objekte pomoću Piton razreda. Ovaj je algoritam gotovo sličan gornjem, ali ga moramo učiniti svestranijim i proći funkciju usporedbe.

Napravit ćemo prilagođenu klasu Car i dodati joj nekoliko polja. Unosimo nekoliko izmjena u algoritam u nastavku kako bismo ga učinili svestranijim. To možemo učiniti pomoću lambda funkcija.

Razumimo sljedeći primjer.

logika prvog reda

Python program

 class Car: # here, we are declaring a class named car def __init__(self, make, model, year): self.make = make # Here, we are using the self to declare the make variables locally self.model = model # Here, we are using the self to declare the model variables locally self.year = year # Here, we are using the self to declare the year variables locally def __str__(self): return str.format(&apos;Make: {}, Model: {}, Year: {}&apos;, self.make, self.model, self.year) # Here, we are returning the format of the strings given def merge(list1, l, r, m, comp_fun): # Here, we are defining a function for merge the list using the compound function left_copy = list1[l:m + 1] # here, we are coping the left part of the list r_sublist = list1[m+1:r+1] # here, we are coping the right part of the list left_copy_index = 0 # here, we are coping the left part indexes of the list r_sublist_index = 0 # here, we are coping the right part indexes of the list sorted_index = l while left_copy_index <len(left_copy) 1 and r_sublist_index < len(r_sublist): # here, we are declaring a while loop using the comp_fun instead of simple comparison operator if comp_fun(left_copy[left_copy_index], r_sublist[r_sublist_index]): checking condition, it is true then will enter block list1[sorted_index]="left_copy[left_copy_index]" left_copy_index="left_copy_index" + else: condition false else sorted_index="sorted_index" len(left_copy): <len(r_sublist): def merge_sort(list1, l, r, comp_fun): merge sort function to given list l>= r: # Here, we are checking the if condition, if it is true then we will enter the block return m = (l + r)//2 # here, we are finding the middle element of the list merge_sort(list1, l, m, comp_fun) # Here, we are calling the merge sort function till the middle number we got merge_sort(list1, m + 1, r, comp_fun) # Here, we are calling the merge sort function from the middle number we got merge(list1, l, r, m, comp_fun) # Here, we are calling the merge function to merge the divided list using the merge # sort function above car1 = Car(&apos;Renault&apos;, &apos;33 Duster&apos;, 2001) car2 = Car(&apos;Maruti&apos;, &apos;Maruti Suzuki Dzire&apos;, 2015) car3 = Car(&apos;Tata motor&apos;, &apos;Jaguar&apos;, 2004) car4 = Car(&apos;Cadillac&apos;, &apos;Seville Sedan&apos;, 1995) list1 = [car1, car2, car3, car4] merge_sort(list1, 0, len(list1) -1, lambda carA, carB: carA.year <carb.year) print(\'cars sorted by year:\') for car in list1: # here, we are declaring the loop to iterate through list1 print(car) printing all data of and list print() merge_sort(list1, 0, len(list1) -1, lambda cara, carb: cara.make < carb.make) make:\') pre> <p> <strong>Output:</strong> </p> <pre> Cars sorted by year: Make: Cadillac, Model: Seville Sedan, Year: 1995 Make: Renault, Model: 33 Duster, Year: 2001 Make: Tata motor, Model: Jaguar, Year: 2004 Make: Maruti, Model: Maruti Suzuki Dzire, Year: 2015 Cars sorted by make: Make: Cadillac, Model: Seville Sedan, Year: 1995 Make: Maruti, Model: Maruti Suzuki Dzire, Year: 2015 Make: Renualt, Model: 33 Duster, Year: 2001 Make: Tata motor, Model: Jaguar, Year: 2004 </pre> <h2>Optimization</h2> <p>We can improve the performance of the merge sort algorithm. First let&apos;s understand the difference between the top-down and bottom-up merge sort. The bottom-up approach sorts the elements of adjacent lists iteratively where the top-down approach breaks down the lists into the two halves.</p> <p>The given list is [10, 4, 2, 12, 1, 3], instead of breaking it down into [10], [4], [2], [12], [1], [3] - we divide into the sub lists which may already sorted: [10, 4], [2], [1, 12], [3] and now are ready to sort them.</p> <p>Merge sort is inefficient algorithm in both time and space for the smaller sub lists. So, insertion sort is more efficient algorithm than the merge sort for the smaller sub lists.</p> <h2>Conclusion</h2> <p>Merge sort is popular and efficient algorithm. It is more efficient algorithm for the large lists. It does not depend on the any unfortunate decisions that lead to bad runtimes.</p> <p>There is one major demerit in the merge sort. It uses the additional memory that is used to store the temporary copies of lists before merging them. However Merge sort is widely used in the software. Its performance is fast and produces the excellent result.</p> <p>We have discussed the merge sort concept in brief and implement it both on simple integer list and on custom objects via a lambda function used for comparison.</p> <hr></carb.year)></len(left_copy)>

Optimizacija

Možemo poboljšati izvedbu algoritma sortiranja spajanjem. Najprije shvatimo razliku između sortiranja spajanjem odozgo prema dolje i odozdo prema gore. Pristup odozdo prema gore razvrstava elemente susjednih popisa iterativno, dok pristup odozgo prema dolje rastavlja popise na dvije polovice.

Dana lista je [10, 4, 2, 12, 1, 3], umjesto da je rastavljamo na [10], [4], [2], [12], [1], [3] - mi dijelimo u podpopise koji su možda već sortirani: [10, 4], [2], [1, 12], [3] i sada su spremni za njihovo sortiranje.

Sortiranje spajanjem je neučinkovit algoritam iu vremenu iu prostoru za manje podpopise. Dakle, sortiranje umetanjem je učinkovitiji algoritam od sortiranja spajanjem za manje podpopise.

Zaključak

Sortiranje spajanjem je popularan i učinkovit algoritam. To je učinkovitiji algoritam za velike liste. Ne ovisi o bilo kakvim nesretnim odlukama koje dovode do lošeg vremena rada.

Postoji jedan veliki nedostatak sortiranja spajanjem. Koristi dodatnu memoriju koja se koristi za pohranjivanje privremenih kopija popisa prije njihovog spajanja. Međutim, sortiranje spajanjem široko se koristi u softveru. Njegova izvedba je brza i daje izvrsne rezultate.

Ukratko smo raspravljali o konceptu sortiranja spajanjem i implementirali ga na jednostavan popis cjelobrojnih brojeva i na prilagođene objekte putem lambda funkcije koja se koristi za usporedbu.