quick sort c with examples
Quicksort v C ++ s ilustrací.
Quicksort je široce používaný algoritmus třídění, který vybírá konkrétní prvek zvaný „pivot“ a rozděluje pole nebo seznam, který se má třídit, na dvě části založené na tomto pivot s0, takže prvky menší než pivot jsou nalevo od seznamu a prvky napravo od seznamu jsou větší než pivot.
Seznam je tedy rozdělen do dvou sublistů. Pro stejnou velikost nemusí být seznamy potřebných nutné. Pak se Quicksort rekurzivně volá, aby tyto dva podlisty seřadil.
=> Podívejte se na průvodce Perfect C ++ Training Guide zde.
Co se naučíte:
- Úvod
- Obecný algoritmus
- Pseudokód pro Quicksort
- Ilustrace
- Příklad C ++
- Příklad Java
- Analýza složitosti algoritmu Quicksort
- 3cestný Quicksort
- Randomizovaný Quicksort
- Quicksort vs. Merge Sort
- Závěr
- Doporučené čtení
Úvod
Quicksort funguje efektivněji a rychleji i pro větší pole nebo seznamy.
V tomto kurzu prozkoumáme více o práci Quicksortu spolu s některými příklady programování algoritmu quicksortu.
Jako pivotní hodnotu můžeme zvolit první, poslední nebo střední hodnotu nebo libovolnou náhodnou hodnotu. Obecná myšlenka je, že nakonec je pivotní hodnota umístěna na správné místo v poli přesunutím ostatních prvků v poli doleva nebo doprava.
Obecný algoritmus
Obecný algoritmus pro Quicksort je uveden níže.
quicksort(A, low, high) begin Declare array A(N) to be sorted low = 1st element; high = last element; pivot if(low Pojďme se nyní podívat na pseudokód pro techniku Quicksort.
Pseudokód pro Quicksort
//pseudocode for quick sort main algorithm procedure quickSort(arr(), low, high) arr = list to be sorted low – first element of array high – last element of array begin if (low Fungování algoritmu dělení je popsáno níže na příkladu.

Na tomto obrázku bereme poslední prvek jako otočný. Vidíme, že pole je postupně rozděleno kolem otočného prvku, dokud v poli nebudeme mít jediný prvek.
Nyní uvádíme ilustraci Quicksortu, abychom lépe porozuměli konceptu.
Ilustrace
Podívejme se na ilustraci algoritmu quicksort. Zvažte následující pole s posledním prvkem jako otočným. První prvek je také označen jako nízký a poslední prvek je vysoký.

jak otevíráte XML soubory
Z obrázku vidíme, že pohybujeme ukazateli vysoko a nízko na obou koncích pole. Kdykoli dolní body ukazují na prvek větší než otočný čep a vysoké ukazují na prvek menší než otočný čep, pak si vyměníme polohy těchto prvků a posuneme dolní a vysoký ukazatel do příslušných směrů.
To se děje, dokud se spodní a horní ukazatel nepřekročí. Jakmile se kříží navzájem, otočný prvek je umístěn na správné pozici a pole je rozděleno na dvě části. Pak jsou obě tato dílčí pole tříděna nezávisle pomocí rekurzivního quicksortu.
Příklad C ++
Níže je uvedena implementace algoritmu Quicksort v C ++.
#include using namespace std; // Swap two elements - Utility function void swap(int* a, int* b) { int t = *a; *a = *b; *b = t; } // partition the array using last element as pivot int partition (int arr(), int low, int high) { int pivot = arr(high); // pivot int i = (low - 1); for (int j = low; j <= high- 1; j++) { //if current element is smaller than pivot, increment the low element //swap elements at i and j if (arr(j) <= pivot) { i++; // increment index of smaller element swap(&arr(i), &arr(j)); } } swap(&arr(i + 1), &arr(high)); return (i + 1); } //quicksort algorithm void quickSort(int arr(), int low, int high) { if (low < high) { //partition the array int pivot = partition(arr, low, high); //sort the sub arrays independently quickSort(arr, low, pivot - 1); quickSort(arr, pivot + 1, high); } } void displayArray(int arr(), int size) { int i; for (i=0; i < size; i++) cout< Výstup:
Vstupní pole
12 23 3 43 51 35 19 45
Pole seřazené pomocí quicksortu
3 12 19 23 35 43 45 51
Zde máme několik rutin, které se používají k rozdělení pole a rekurzivnímu volání quicksortu, aby se seřadil oddíl, základní funkce quicksortu a obslužné funkce k zobrazení obsahu pole a odpovídajícím způsobem zaměnily dva prvky.
Nejprve zavoláme funkci quicksort se vstupním polem. Uvnitř funkce quicksort nazýváme funkci oddílu. Ve funkci oddílu použijeme poslední prvek jako otočný prvek pro pole. Jakmile je rozhodnuto o otočení, pole je rozděleno na dvě části a poté je volána funkce quicksort pro nezávislé třídění obou dílčích polí.
Když se funkce quicksort vrátí, pole je tříděno tak, že prvek pivot je na správném místě a prvky menší než pivot jsou na levé straně pivot a prvky větší než pivot na pravé straně pivot.
Dále implementujeme algoritmus quicksort v Javě.
Příklad Java
// Quicksort implementation in Java class QuickSort { //partition the array with last element as pivot int partition(int arr(), int low, int high) { int pivot = arr(high); int i = (low-1); // index of smaller element for (int j=low; j Výstup:
Vstupní pole
12 23 3 43 51 35 19 45
Pole po třídění pomocí rychlého třídění
3 12 19 23 35 43 45 51
I v implementaci Java jsme použili stejnou logiku, jakou jsme použili v implementaci C ++. Poslední prvek v poli jsme použili jako pivot a na poli se provádí quicksort, abychom umístili pivotní prvek do správné polohy.
jak aktualizovat Windows 10 BIOS
Analýza složitosti algoritmu Quicksort
Čas, který quicksort setřídí pole, závisí na strategii nebo metodě vstupního pole a oddílu.
Pokud k je počet prvků menší než pivot a n je celkový počet prvků, pak lze obecný čas, který zabere quicksort, vyjádřit takto:
T (n) = T (k) + T (n-k-1) + O (n)
Zde T (k) a T (n-k-1) jsou čas potřebný pro rekurzivní volání a O (n) je čas potřebný pro rozdělení hovoru.
Pojďme analyzovat tuto časovou složitost pro quicksort podrobně.
# 1) Nejhorší případ : Nejhorší případ v technice rychlého třídění nastává většinou tehdy, když jako pivot vybereme nejnižší nebo nejvyšší prvek v poli. (Na obrázku výše jsme jako pivot vybrali nejvyšší prvek). V takové situaci nastane nejhorší případ, když je pole, které má být tříděno, již seřazeno vzestupně nebo sestupně.
Výše uvedený výraz pro celkový čas se tedy mění jako:
T (n) = T (0) + T (n-1) + O (n) který vyřeší Nadva)
# 2) Nejlepší případ: Nejlepší případ pro rychlé řazení vždy nastane, když je vybraný otočný prvek uprostřed pole.
Opakování pro nejlepší případ je tedy:
c ++ ve srovnání s java
T (n) = 2T (n / 2) + O (n) = O (nlogn)
# 3) Průměrný případ: Abychom mohli analyzovat průměrný případ pro quicksort, měli bychom vzít v úvahu všechny permutace pole a poté vypočítat čas, který každá z těchto permutací zabere. Stručně řečeno, průměrná doba pro quicksort se také změní na O (nlogn).
Níže jsou uvedeny různé složitosti pro techniku Quicksort:
Nejhorší časová složitost O (n 2) stabilita Není stabilní, protože dva prvky se stejnými hodnotami nebudou umístěny ve stejném pořadí. Stabilní - ve tříděném výstupu se zobrazí dva prvky se stejnými hodnotami ve stejném pořadí. Nejlepší časová složitost O (n * log n) Průměrná časová složitost O (n * log n) Složitost prostoru O (n * log n)
Můžeme implementovat quicksort mnoha různými způsoby pouhou změnou volby pivotního prvku (střední, první nebo poslední), nejhorší případ se však pro quicksort vyskytuje jen zřídka.
3cestný Quicksort
V originální technice quicksort obvykle vybereme prvek pivot a poté rozdělíme pole do podoblastí kolem tohoto pivot tak, aby jedno dílčí pole sestávalo z prvků menších než pivot a další sestávalo z prvků větších než pivot.
Ale co když vybereme prvek pivot a v poli je více než jeden prvek, který se rovná pivot?
Například, zvažte následující pole {5,76,23,65,4,4,5,4,1,1,2,2,2,2}. Pokud provedeme jednoduchý quicksort na tomto poli a vybereme 4 jako otočný prvek, opravíme pouze jeden výskyt prvku 4 a zbytek bude rozdělen spolu s ostatními prvky.
Místo toho, pokud použijeme třícestný quicksort, rozdělíme pole (l… r) do tří dílčích polí takto:
- Pole (l… i) - Zde je i pivot a toto pole obsahuje prvky menší než pivot.
- Pole (i + 1… j-1) - Obsahuje prvky, které se rovnají otočnému čepu.
- Pole (j… r) - Obsahuje prvky větší než pivot.
3směrný quicksort lze tedy použít, když máme v poli více než jeden redundantní prvek.
Randomizovaný Quicksort
Technika rychlého řazení se nazývá randomizovaná technika rychlého řazení, když k výběru prvku otáčení použijeme náhodná čísla. V randomizovaném quicksortu se tomu říká „centrální pivot“ a rozděluje pole takovým způsobem, že každá strana má alespoň ¼ prvků.
Níže je uveden pseudokód pro randomizovaný rychlý výběr:
// Sorts an array arr(low..high) using randomized quick sort randomQuickSort(array(), low, high) array – array to be sorted low – lowest element in array high – highest element in array begin 1. If low >= high, then EXIT. //select central pivot 2. While pivot 'pi' is not a Central Pivot. (i) Choose uniformly at random a number from (low..high). Let pi be the randomly picked number. (ii) Count elements in array(low..high) that are smaller than array(pi). Let this count be a_low. (iii) Count elements in array(low..high) that are greater than array(pi). Let this count be a_high. (iv) Let n = (high-low+1). If a_low >= n/4 and a_high >= n/4, then pi is a central pivot. //partition the array 3. Partition array(low..high) around the pivot pi. 4. // sort first half randomQuickSort(array, low, a_low-1) 5. // sort second half randomQuickSort(array, high-a_high+1, high) end procedure
Ve výše uvedeném kódu na „randomQuickSort“ v kroku 2 vybereme centrální pivot. V kroku 2 je pravděpodobnost, že vybraný prvek bude středovým otočným čepem, je ½. Očekává se tedy, že smyčka v kroku 2 poběží dvakrát. Časová složitost pro krok 2 v randomizovaném rychlém řazení je tedy O (n).
Použití smyčky k výběru centrálního otočného čepu není ideální způsob, jak implementovat randomizovaný quicksort. Místo toho můžeme náhodně vybrat prvek a nazvat jej centrálním otočením nebo přeskupit prvky pole. Očekávaná nejhorší časová složitost pro randomizovaný algoritmus rychlého řazení je O (nlogn).
Quicksort vs. Merge Sort
V této části probereme hlavní rozdíly mezi rychlým tříděním a sloučením.
Parametr porovnání Rychlé třídění Sloučit třídění rozdělení Pole je rozděleno kolem otočného prvku a nemusí být nutně vždy na dvě poloviny. Lze jej rozdělit v libovolném poměru. Pole je rozděleno na dvě poloviny (n / 2). Složitost nejhoršího případu O (n 2) - v nejhorším případě je zapotřebí hodně srovnání. O (nlogn) - stejné jako průměrný případ Využití datových souborů S většími datovými sadami nelze dobře pracovat. Funguje dobře se všemi datovými sadami bez ohledu na velikost. Další prostor Na místě - nepotřebuje další prostor. Není na místě - potřebuje další prostor pro uložení pomocného pole. Metoda třídění Interní - data jsou tříděna v hlavní paměti. Externí - používá externí paměť pro ukládání datových polí. Účinnost Rychlejší a efektivnější pro malé seznamy. Rychlý a efektivní pro větší seznamy. Pole / propojené seznamy Výhodnější pro pole. Funguje dobře pro propojené seznamy.
Závěr
Jak název napovídá, quicksort je algoritmus, který třídí seznam rychle než jakékoli jiné třídicí algoritmy. Stejně jako sloučení, rychlé třídění také přijímá strategii rozdělení a dobývání.
Jak jsme již viděli, pomocí rychlého řazení rozdělíme seznam na dílčí pole pomocí prvku pivot. Pak jsou tato dílčí pole samostatně tříděna. Na konci algoritmu je celé pole kompletně tříděno.
Quicksort je rychlejší a funguje efektivně při třídění datových struktur. Quicksort je populární třídicí algoritmus a někdy je dokonce upřednostňován před sloučením.
V našem dalším kurzu se budeme podrobněji zabývat tříděním Shell.
=> Dávejte pozor na jednoduchou sérii školení C ++ zde.
Doporučené čtení