Ниже приведена типичная рекурсивная реализация быстрой сортировки, которая использует последний элемент в качестве сводной.
C ++
#include <bits/stdc++.h>
using namespace std;
void swap( int * a, int * b)
{
int temp = *a;
*a = *b;
*b = temp;
}
int partition( int arr[], int l, int h)
{
int x = arr[h];
int i = (l - 1);
for ( int j = l; j <= h - 1; j++) {
if (arr[j] <= x) {
i++;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[h]);
return (i + 1);
}
void quickSort( int A[], int l, int h)
{
if (l < h) {
int p = partition(A, l, h);
quickSort(A, l, p - 1);
quickSort(A, p + 1, h);
}
}
int main()
{
int n = 5;
int arr[n] = { 4, 2, 6, 9, 2 };
quickSort(arr, 0, n - 1);
for ( int i = 0; i < n; i++) {
cout << arr[i] << " " ;
}
return 0;
}
|
Джава
import java.util.*;
class QuickSort {
static int partition( int arr[], int low, int high)
{
int pivot = arr[high];
int i = (low - 1 );
for ( int j = low; j <= high - 1 ; j++) {
if (arr[j] <= pivot) {
i++;
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
int temp = arr[i + 1 ];
arr[i + 1 ] = arr[high];
arr[high] = temp;
return i + 1 ;
}
static void qSort( int arr[], int low, int high)
{
if (low < high) {
int pi = partition(arr, low, high);
qSort(arr, low, pi - 1 );
qSort(arr, pi + 1 , high);
}
}
public static void main(String args[])
{
int n = 5 ;
int arr[] = { 4 , 2 , 6 , 9 , 2 };
qSort(arr, 0 , n - 1 );
for ( int i = 0 ; i < n; i++) {
System.out.print(arr[i] + " " );
}
}
}
|
python3
def partition(arr, low, high):
i = (low - 1 )
pivot = arr[high]
for j in range (low, high):
if arr[j] < = pivot:
i + = 1
arr[i], arr[j] = arr[j], arr[i]
arr[i + 1 ], arr[high] = arr[high], arr[i + 1 ]
return (i + 1 )
def quickSort(arr, low, high):
if low < high:
pi = partition(arr, low, high)
quickSort(arr, low, pi - 1 )
quickSort(arr, pi + 1 , high)
if __name__ = = '__main__' :
arr = [ 4 , 2 , 6 , 9 , 2 ]
n = len (arr)
quickSort(arr, 0 , n - 1 )
for i in range (n):
print (arr[i], end = " " )
|
C #
using System;
class GFG {
static int partition( int [] arr,
int low, int high)
{
int temp;
int pivot = arr[high];
int i = (low - 1);
for ( int j = low; j <= high - 1; j++) {
if (arr[j] <= pivot) {
i++;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
temp = arr[i + 1];
arr[i + 1] = arr[high];
arr[high] = temp;
return i + 1;
}
static void qSort( int [] arr, int low,
int high)
{
if (low < high) {
int pi = partition(arr, low, high);
qSort(arr, low, pi - 1);
qSort(arr, pi + 1, high);
}
}
public static void Main()
{
int n = 5;
int [] arr = { 4, 2, 6, 9, 2 };
qSort(arr, 0, n - 1);
for ( int i = 0; i < n; i++)
Console.Write(arr[i] + " " );
}
}
|
PHP
<?php
function swap(& $a , & $b )
{
$temp = $a ;
$a = $b ;
$b = $temp ;
}
function partition (& $arr , $l , $h )
{
$x = $arr [ $h ];
$i = ( $l - 1);
for ( $j = $l ; $j <= $h - 1; $j ++)
{
if ( $arr [ $j ] <= $x )
{
$i ++;
swap ( $arr [ $i ], $arr [ $j ]);
}
}
swap ( $arr [ $i + 1], $arr [ $h ]);
return ( $i + 1);
}
function quickSort(& $A , $l , $h )
{
if ( $l < $h )
{
$p = partition( $A , $l , $h );
quickSort( $A , $l , $p - 1);
quickSort( $A , $p + 1, $h );
}
}
$n = 5;
$arr = array (4, 2, 6, 9, 2);
quickSort( $arr , 0, $n - 1);
for ( $i = 0; $i < $n ; $i ++)
{
echo $arr [ $i ] . " " ;
}
?>
|
Выход:
2 2 4 6 9
Вышеуказанная реализация может быть оптимизирована многими способами
1) Приведенная выше реализация использует последний индекс в качестве точки разворота. Это вызывает наихудшее поведение на уже отсортированных массивах, что часто встречается. Эту проблему можно решить, выбрав либо произвольный индекс для стержня, либо выбрав средний индекс раздела, либо выбрав медиану первого, среднего и последнего элемента раздела для стержня. (Смотрите это для деталей)
2) Чтобы уменьшить глубину рекурсии, вернитесь сначала для меньшей половины массива и используйте хвостовой вызов для рекурсии в другую.
3) Сортировка вставок работает лучше для небольших подмассивов. Сортировка вставки может использоваться для вызовов на таких небольших массивах (т. Е. Когда длина меньше порога t, определенного экспериментально). Например, эта реализация библиотеки qsort использует сортировку вставкой ниже размера 7.
Несмотря на приведенные выше оптимизации, функция остается рекурсивной и использует стек вызовов функций для хранения промежуточных значений l и h. Стек вызовов функций хранит другую бухгалтерскую информацию вместе с параметрами. Кроме того, вызовы функций включают в себя издержки, такие как сохранение записи активации функции вызывающей стороны и затем возобновление выполнения.
Вышеуказанная функция может быть легко преобразована в итерационную версию с помощью вспомогательного стека. Ниже приведена итеративная реализация приведенного выше рекурсивного кода.
C ++
#include <bits/stdc++.h>
using namespace std;
void swap( int * a, int * b)
{
int t = *a;
*a = *b;
*b = t;
}
int partition( int arr[], int l, int h)
{
int x = arr[h];
int i = (l - 1);
for ( int j = l; j <= h - 1; j++) {
if (arr[j] <= x) {
i++;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[h]);
return (i + 1);
}
void quickSortIterative( int arr[], int l, int h)
{
int stack[h - l + 1];
int top = -1;
stack[++top] = l;
stack[++top] = h;
while (top >= 0) {
h = stack[top--];
l = stack[top--];
int p = partition(arr, l, h);
if (p - 1 > l) {
stack[++top] = l;
stack[++top] = p - 1;
}
if (p + 1 < h) {
stack[++top] = p + 1;
stack[++top] = h;
}
}
}
void printArr( int arr[], int n)
{
int i;
for (i = 0; i < n; ++i)
cout << arr[i] << " " ;
}
int main()
{
int arr[] = { 4, 3, 5, 2, 1, 3, 2, 3 };
int n = sizeof (arr) / sizeof (*arr);
quickSortIterative(arr, 0, n - 1);
printArr(arr, n);
return 0;
}
|
С
#include <stdio.h>
void swap( int * a, int * b)
{
int t = *a;
*a = *b;
*b = t;
}
int partition( int arr[], int l, int h)
{
int x = arr[h];
int i = (l - 1);
for ( int j = l; j <= h - 1; j++) {
if (arr[j] <= x) {
i++;
swap(&arr[i], &arr[j]);
}
}
swap(&arr[i + 1], &arr[h]);
return (i + 1);
}
void quickSortIterative( int arr[], int l, int h)
{
int stack[h - l + 1];
int top = -1;
stack[++top] = l;
stack[++top] = h;
while (top >= 0) {
h = stack[top--];
l = stack[top--];
int p = partition(arr, l, h);
if (p - 1 > l) {
stack[++top] = l;
stack[++top] = p - 1;
}
if (p + 1 < h) {
stack[++top] = p + 1;
stack[++top] = h;
}
}
}
void printArr( int arr[], int n)
{
int i;
for (i = 0; i < n; ++i)
printf ( "%d " , arr[i]);
}
int main()
{
int arr[] = { 4, 3, 5, 2, 1, 3, 2, 3 };
int n = sizeof (arr) / sizeof (*arr);
quickSortIterative(arr, 0, n - 1);
printArr(arr, n);
return 0;
}
|
Джава
import java.util.*;
class QuickSort {
static int partition( int arr[], int low, int high)
{
int pivot = arr[high];
int i = (low - 1 );
for ( int j = low; j <= high - 1 ; j++) {
if (arr[j] <= pivot) {
i++;
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
int temp = arr[i + 1 ];
arr[i + 1 ] = arr[high];
arr[high] = temp;
return i + 1 ;
}
static void quickSortIterative( int arr[], int l, int h)
{
int [] stack = new int [h - l + 1 ];
int top = - 1 ;
stack[++top] = l;
stack[++top] = h;
while (top >= 0 ) {
h = stack[top--];
l = stack[top--];
int p = partition(arr, l, h);
if (p - 1 > l) {
stack[++top] = l;
stack[++top] = p - 1 ;
}
if (p + 1 < h) {
stack[++top] = p + 1 ;
stack[++top] = h;
}
}
}
public static void main(String args[])
{
int arr[] = { 4 , 3 , 5 , 2 , 1 , 3 , 2 , 3 };
int n = 8 ;
quickSortIterative(arr, 0 , n - 1 );
for ( int i = 0 ; i < n; i++) {
System.out.print(arr[i] + " " );
}
}
}
|
питон
def partition(arr, l, h):
i = ( l - 1 )
x = arr[h]
for j in range (l, h):
if arr[j] < = x:
i = i + 1
arr[i], arr[j] = arr[j], arr[i]
arr[i + 1 ], arr[h] = arr[h], arr[i + 1 ]
return (i + 1 )
def quickSortIterative(arr, l, h):
size = h - l + 1
stack = [ 0 ] * (size)
top = - 1
top = top + 1
stack[top] = l
top = top + 1
stack[top] = h
while top > = 0 :
h = stack[top]
top = top - 1
l = stack[top]
top = top - 1
p = partition( arr, l, h )
if p - 1 > l:
top = top + 1
stack[top] = l
top = top + 1
stack[top] = p - 1
if p + 1 < h:
top = top + 1
stack[top] = p + 1
top = top + 1
stack[top] = h
arr = [ 4 , 3 , 5 , 2 , 1 , 3 , 2 , 3 ]
n = len (arr)
quickSortIterative(arr, 0 , n - 1 )
print ( "Sorted array is:" )
for i in range (n):
print ( "% d" % arr[i]),
|
C #
using System;
class GFG {
static int partition( int [] arr, int low,
int high)
{
int temp;
int pivot = arr[high];
int i = (low - 1);
for ( int j = low; j <= high - 1; j++) {
if (arr[j] <= pivot) {
i++;
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
temp = arr[i + 1];
arr[i + 1] = arr[high];
arr[high] = temp;
return i + 1;
}
static void quickSortIterative( int [] arr,
int l, int h)
{
int [] stack = new int [h - l + 1];
int top = -1;
stack[++top] = l;
stack[++top] = h;
while (top >= 0) {
h = stack[top--];
l = stack[top--];
int p = partition(arr, l, h);
if (p - 1 > l) {
stack[++top] = l;
stack[++top] = p - 1;
}
if (p + 1 < h) {
stack[++top] = p + 1;
stack[++top] = h;
}
}
}
public static void Main()
{
int [] arr = { 4, 3, 5, 2, 1, 3, 2, 3 };
int n = 8;
quickSortIterative(arr, 0, n - 1);
for ( int i = 0; i < n; i++)
Console.Write(arr[i] + " " );
}
}
|
PHP
<?php
function swap ( & $a , & $b )
{
$t = $a ;
$a = $b ;
$b = $t ;
}
function partition (& $arr , $l , $h )
{
$x = $arr [ $h ];
$i = ( $l - 1);
for ( $j = $l ; $j <= $h - 1; $j ++)
{
if ( $arr [ $j ] <= $x )
{
$i ++;
swap ( $arr [ $i ], $arr [ $j ]);
}
}
swap ( $arr [ $i + 1], $arr [ $h ]);
return ( $i + 1);
}
function quickSortIterative (& $arr , $l , $h )
{
$stack = array_fill (0, $h - $l + 1, 0);
$top = -1;
$stack [ ++ $top ] = $l ;
$stack [ ++ $top ] = $h ;
while ( $top >= 0 )
{
$h = $stack [ $top -- ];
$l = $stack [ $top -- ];
$p = partition( $arr , $l , $h );
if ( $p -1 > $l )
{
$stack [ ++ $top ] = $l ;
$stack [ ++ $top ] = $p - 1;
}
if ( $p +1 < $h )
{
$stack [ ++ $top ] = $p + 1;
$stack [ ++ $top ] = $h ;
}
}
}
function printArr( $arr , $n )
{
for ( $i = 0; $i < $n ; ++ $i )
echo $arr [ $i ]. " " ;
}
$arr = array (4, 3, 5, 2, 1, 3, 2, 3);
$n = count ( $arr );
quickSortIterative( $arr , 0, $n - 1 );
printArr( $arr , $n );
?>
|
Выход:
1 2 2 3 3 3 4 5
Вышеупомянутые оптимизации для быстрой рекурсивной сортировки также могут быть применены к итерационной версии.
1) Процесс разбиения одинаков как в рекурсивном, так и итеративном. Те же методы для выбора оптимального центра также могут быть применены к итерационной версии.
2) Чтобы уменьшить размер стека, сначала нажмите индексы меньшей половины.
3) Используйте сортировку вставки, когда размер уменьшается ниже экспериментально рассчитанного порога.
Ссылки:
http://en.wikipedia.org/wiki/Quicksort
Эта статья составлена Aashish Barnwal и рецензирована командой GeeksforGeeks. Пожалуйста, пишите комментарии, если вы обнаружите что-то неправильное или вы хотите поделиться дополнительной информацией по обсуждаемой выше теме.
Рекомендуемые посты:
Итеративная быстрая сортировка
0.00 (0%) 0 votes