Felfedező vagy feltaláló | John von Neumann |
---|---|
A felfedezés dátuma | 1945 |
Kapcsolódó kérdések | Rendezés összehasonlítás alapján ( en ) , stabil rendezési algoritmus ( en ) |
Adatszerkezetek | Táblázat , egyesítési algoritmus ( in ) |
Kezdetekor | Timsort |
Legrosszabb esetben | |
---|---|
Átlagos | |
Legjobb eset |
Legrosszabb esetben | |
---|---|
Legjobb eset |
A számítástechnika , egyesítés válogatás , vagy dichotóm válogatás, egy stabil összehasonlítás rendezési algoritmus . Az n méretű bemenet időbeli összetettsége n log n nagyságrendű , ami aszimptotikusan optimális. Ez a rendezés az osztás és meghódítás algoritmikus technikán alapszik . Az algoritmus fő művelete az összevonás , amely két rendezett lista összekapcsolásából áll. Az algoritmus hatékonysága abból adódik, hogy két rendezett lista lineáris időben egyesíthető.
Az összeolvadás rendezését természetesen leírják a listák, és az ilyen struktúrákon egyszerre van a legegyszerűbb és leggyorsabb. Ugyanakkor tömbökön is működik . A táblák egyesítésének egyszerűbb verziója hatékonyságában összehasonlítható a gyors rendezéssel , de nem működik a helyén : további, ideiglenes adatterületre van szükség, amely akkora, mint a bemenet (bonyolultabb verziók elvégezhetők a következőn: de lassabbak). A listákon összetettsége optimális, nagyon egyszerűen megvalósítható, és nem igényel másolatot az ideiglenes memóriában.
Két rendezett listából könnyen fel lehet építeni egy rendezett listát, amely tartalmazza a két listából származó elemeket (azok * fúziója *). Az összevonás-rendezési algoritmus elve ezen a megfigyelésen alapszik: a felépítendő lista legkisebb eleme vagy az első lista legkisebb eleme, vagy a második lista legkisebb eleme. Így felépíthetjük a listaelemet elemenként úgy, hogy néha eltávolítjuk az első lista első elemét, néha a második lista első elemét (valójában a kettő közül a kisebbet, feltételezve, hogy a két lista egyik sem üres., egyébként a válasz azonnali).
Ezt a folyamatot fúziónak hívják, és az alábbiakban kidolgozott rendezési algoritmus középpontjában áll.
Az algoritmust természetesen rekurzív módon írják le.
Álkódban:
entrée : un tableau T sortie : une permutation triée de T fonction triFusion(T[1, …, n]) si n ≤ 1 renvoyer T sinon renvoyer fusion(triFusion(T[1, …, n/2]), triFusion(T[n/2 + 1, …, n])) entrée : deux tableaux triés A et B sortie : un tableau trié qui contient exactement les éléments des tableaux A et B fonction fusion(A[1, …, a], B[1, …, b]) si A est le tableau vide renvoyer B si B est le tableau vide renvoyer A si A[1] ≤ B[1] renvoyer A[1] ⊕ fusion(A[2, …, a], B) sinon renvoyer B[1] ⊕ fusion(A, B[2, …, b])Az algoritmus azért fejeződik be, mert a rendezendő tömb mérete szigorúan csökken a hívások során. A egyesítési A és B jelentése ahol a a mérete a és b jelentése a mérete B. A egyesítési fajta egy tömb T jelentése ahol n a méret a tömb T. A szimbólum ⊕ itt jelöli összefűzöttjével festmények.
A következő algoritmus részletes, így lefordítható bármely imperatív nyelvre . A rendezni kívánt lista mérete n . Az algoritmus tömörsége és hatékonysága érdekében feltételezzük, hogy a rendezendő listának legalább 2 eleme van, és hogy:
A lista minden esetben a paraméterként átadott p hivatkozás után rendeződik , vagyis a p utód linkje lesz a legkisebb a listában. Kicsit kevésbé tömör, de ezektől a strukturális korlátoktól mentes leírások léteznek.
fonction trier(p, n) Q := n/2 (division entière) P := n-Q si P >= 2 q := trier(p, P) si Q >= 2 trier(q, Q) sinon q := p.suivant fin q := fusionner(p, P, q, Q) renvoyer q fin fonction fusionner(p, P, q, Q) pour i allant de 0 à taille(p)-1 faire si valeur(p.suivant) > valeur(q.suivant) déplacer le maillon q.suivant après le maillon p si Q = 1 quitter la boucle Q := Q-1 sinon si P = 1 tant que Q >= 1 q := q.suivant Q := Q-1 fin quitter la boucle fin P := P-1 fin p := p.suivant fin renvoyer q finA következő link elmozdulása q után egy p link ideiglenes t mutatóra van szükség . Ha a lista egyszerűen láncolva van, a mozgást a linkek cseréje hajtja végre:
t := q.suivant q.suivant := t.suivant t.suivant := p.suivant p.suivant := tHa a lista kétszeresen láncolt és kör alakú, akkor a mozgást a linkek ezen cseréje hajtja végre:
t := q.suivant q.suivant := t.suivant q.suivant.précédent := q t.précédent := p t.suivant := p.suivant p.suivant.précédent := t p.suivant := tAz így ismertetett algoritmus nagyon könnyen hibridizálható más fajtákkal. Ez egy feltétel hozzáadásával történik a rendezési függvény legelső sorában ( p , n ). Kis allistákon az a szerepe, hogy az összes műveletet valamilyen másodfokú bonyolultsággal, de a gyakorlatban gyorsabban helyettesítse. A következőkben a P> = 2 és a Q> = 2 feltételek eltávolíthatók.
Asztalokkal a helyszínen rendezhetjük vagy sem. Ekkor vázlatosan három lehetőség van a memóriakezelésre:
Egyesítés [1; 2; 5] és [3; 4]: Az összevont lista első eleme a két bemeneti lista egyikének első eleme lesz (1 vagy 3), mivel ezek rendezett listák.
Futtassuk át a következő hívásokat tri_fusion([6, 1, 2, 5, 4, 7, 3]) :
tri_fusion([6, 1, 2, 5, 4, 7, 3]) [6, 1, 2, 5] [4, 7, 3] tri_fusion([6, 1, 2, 5]) [6, 1] [2, 5] tri_fusion([6, 1]) [6] [1] tri_fusion([6]) --> [6] tri_fusion([1]) --> [1] '''fusion''' de [6] et [1] : [1, 6] --> [1, 6] tri_fusion([2, 5]) [2] [5] tri_fusion([2]) --> [2] tri_fusion([5]) --> [5] '''fusion''' de [2] et [5] : [2, 5] --> [2, 5] '''fusion''' de [1, 6] et [2, 5] : [1, 2, 5, 6] --> [1, 2, 5, 6] tri_fusion([4, 7, 3]) [4] [7, 3] tri_fusion([4]) --> [4] tri_fusion([7, 3]) [7] [3] tri_fusion([7]) --> [7] tri_fusion([3]) --> [3] '''fusion''' de [7] et [3] : [3, 7] --> [3, 7] '''fusion''' de [4] et [3, 7] : [3, 4, 7] --> [3, 4, 7] '''fusion''' de [1, 2, 5, 6] et [3, 4, 7] : [1, 2, 3, 4, 5, 6, 7] --> [1, 2, 3, 4, 5, 6, 7]Ne feledje, hogy az egyesítés függvényt mindig rendezett listákon hívják meg.