Quick Sort

From Algorithm wiki

Jump to: navigation, search
Related content:

Contents

[edit] Introduction

As its name implies, quicksort is the fastest known sorting algorithm in practice. Its average running time is O(n log n). It is very fast, mainly due to a very tight and highly optimized inner loop.Quicksort is a divide-et-impera method for sorting. It works by partitioning an array into two parts, then sorting the parts independently.

[edit] Pseudocode

Quicksort(A,p,r) {
    if (p < r) {
       q <- Partition(A,p,r)
       Quicksort(A,p,q)
       Quicksort(A,q+1,r)
    }
}



Partition(A,p,r) {
    x <- A[p]
    i <- p-1
    j <- r+1
    while (True) {
        repeat
            j <- j-1
        until (A[j] <= x)
        repeat
            i <- i+1
        until (A[i] >= x)
        if (i<-> A[j])
        else 
            return(j)
    }
}

[edit] C Code

#include <stdio.h>

void swap(int l[], int i, int j)
{  int dummy;
   dummy=l[j];
   l[j]=l[i];
   l[i]=dummy;  
 }

int partions(int l[],int low,int high)
{
    int prvotkey=l[low];
    while (low<high)
    {
        while (low<high && l[high]>=prvotkey)
            --high;
        swap(l,high,low);
        while (low<high && l[low]<=prvotkey) 
            ++low;
        swap(l,high,low);      
    }

    return low;
}

void qsort(int l[],int low,int high)
{
    int prvotloc;
    if(low<high)
    {
        prvotloc=partions(l,low,high);    
        qsort(l,low,prvotloc); 
        qsort(l,prvotloc+1,high); 
    }
}

void quicksort(int l[],int n)
{
    qsort(l,0,n); 
}

void main()
{
    int a[11]={103,2,32,43,23,45,36,57,14,27,39};
    int b,c;
    for (b=0;b<=10;b++)
        printf("%3d ",a[b]);

    printf("\n");
    quicksort(a,10);

    for(c=0;c<=10;c++)
        printf("%3d ",a[c]);

}

[edit] PHP Code

function quick_sort($array){
  if (count($array) <= 1) return $array; 

  $key = $array[0];
  $left_arr = array();
  $right_arr = array();
  for ($i=1; $i<count($array); $i++){
    if ($array[$i] <= $key)
      $left_arr[] = $array[$i];
    else
      $right_arr[] = $array[$i];
  }
  $left_arr = quick_sort($left_arr);
  $right_arr = quick_sort($right_arr); 

  return array_merge($left_arr, array($key), $right_arr);
}

Fail. That is a mergesort.

[edit] C++ Code

[edit] Recursive

#undef  SORT_MAX
#define SORT_MAX  150

template <typename Type> inline
void Quick(Type *pF, Type *pL)
{
	if (pL-pF <= SORT_MAX) {       // partial insertion sorting
		Insertion(pF, pL);     // because of stack overflow
	} else {
		Type *pM = Partition(pF, pL, GetPivot(pF, pL));
		Quick(pF, pM);
		Quick(pM, pL);
	}
}

template <typename Type> inline
Type *Partition(Type *pF, Type *pL, Type pivot)
{
	for (pF--; ;) {
		while (*(++pF) < pivot);
		while (*(--pL) > pivot);
		if (pF>=pL) { return pF; }
		std::iter_swap(pF, pL);        // #include <algorithm>
	}
}

template <typename Type> inline
Type GetPivot(Type *pF, Type *pL)
{	
	return GetMedian(Type(*pF), Type(*(pF+(pL-pF)/2)), Type(*(pL-1)));	// using first, mid and last
}

template <typename Type> inline
Type GetMedian(Type x, Type y, Type z)
{
	if (x < y)	{ return (y < z ? y : x < z ? z : x); }
	else		{ return (x < z ? x : y < z ? z : y); }
}

[edit] Loop (using user's stack)

//////////////////////////// 사용자 스택을 이용한 반복문으로 빠른 정렬 구현
#undef  SORT_MAX
#define SORT_MAX  150    // (many : 100~200, a few : 5~25)

template <typename Type> inline
void Quick_Loop(Type *pF, Type *pL)
{
    std::stack<Type *> pBuf;        // #include <stack>
    do {
        if (pL-pF <= SORT_MAX) {
            Insertion(pF, pL);
        } else {
            Type *pM = Partition(pF, pL, GetPivot(pF, pL));
            pBuf.push(pM);      pBuf.push(pL);              // [pM, pL)
            pBuf.push(pF);      pBuf.push(pM);              // [pF, pM)
        }

        if (pBuf.empty()) { break; }
        pL = pBuf.top();     pBuf.pop();
        pF = pBuf.top();     pBuf.pop();
    } while (1);
}

#undef SORT_MAX

[edit] C# 3.0 Code

The algorithm applies to every generic index-based list, inclusively arrays.

using System;
using System.Collections.Generic;


public static class Sorter <T> where T : IComparable
{
    private static void QuickSort(IList<T> list, int left, int right)
    {
        if (left < right)
        {
            T pivotElement = list[right];
            int i = left - 1;
            int j = right + 1;

            //Search for the biggest item left to the pivot element and for
            //the smallest item right to the pivot element and exchange both.
            while (i <= j)
            {
                do { i++; } while (i <= j && IsSmaller(list[i], pivotElement));
                do { j--; } while (i <= j && IsBigger (list[j], pivotElement));
                if (i < j) Exchange(list, i, j);
            }

            QuickSort(list, left, j);
            QuickSort(list, i, right);
        }
    }
}

Exchange method:

private static void Exchange(IList<T> list, int index1, int index2)
{
    T tmp = list[index1];
    list[index1] = list[index2];
    list[index2] = tmp;
}

The comparing methods:

private static bool IsSmaller(T item1, T item2)
{
    return item1.CompareTo(item2) < 0;
}

private static bool IsBigger(T item1, T item2)
{
    return item1.CompareTo(item2) > 0;
}

[edit] Another C# Code

void Quicksort(int[] v, int prim, int ult) {

       if (prim < ult)
       {
               /* Selecciona un elemento del vector y coloca los menores
                  que él a su izquierda y los mayores a su derecha */
               int p = Pivote(v, prim, ult, ult);

               /* Repite el proceso para cada una de las 
                  particiones generadas en el paso anterior */
               Quicksort(v, prim, p - 1);
               Quicksort(v, p + 1, ult);
       }

}

/* Implementación no clásica de la función Pivote. En lugar de recorrer el vector simultáneamente desde ambos extremos hasta el cruce de índices, se recorre desde el comienzo hasta el final */ int Pivote(int[] v, int prim, int ult, int piv) {

       int p = v[piv];
       int j = prim;

       // Mueve el pivote a la última posición del vector
       Intercambia(v, piv, ult);

       /* Recorre el vector moviendo los elementos menores
          o iguales que el pivote al comienzo del mismo */
       for (int i = prim; i < ult; i++)
       {
               if (v[i] <= p)
               {
                       Intercambia(v, i, j);
                       j++;
               }
       }

       // Mueve el pivote a la posición que le corresponde
       Intercambia(v, j, ult);

       return j;

}

void Intercambia(int[] v, int a, int b) {

       if (a != b)
       {
               int tmp = v[a];
               v[a] = v[b];
               v[b] = tmp;
       }

}

[edit] Java 6 Code

public int [] quickSort(int[] array, int anfang, int ende){
	if (ende> anfang){
		int pivot = anfang;
		int mitte = anfang;
		
		for (int i=anfang+1; i<= ende; i++){
			if (array[i]< array[pivot]){
				mitte++;
				swap(array, i, mitte);
			}
		}
		swap(array, pivot, mitte);
		
		array= quickSort(array, mitte+1, ende);
		array =quickSort(array, anfang, mitte-1);
		
	}
	return array;
}

private void swap(int[] result, int a, int b){
	int temp = result[a];
	result[a] = result[b];
	result[b] = temp; 
}

[edit] Java Code

static void sort(int a[], int lo0, int hi0) {
    int lo = lo0;
    int hi = hi0;
    if (lo >= hi) {
        return;
    }
    int mid = a[(lo + hi) / 2];
    while (lo < hi) {
        while (lo<hi && a[lo] < mid) {
            lo++;
        }
        while (lo<hi && a[hi] >= mid) {
            hi--;
        }
        if (lo < hi) {
            int T = a[lo];
            a[lo] = a[hi];
            a[hi] = T;
        }
    }
    if (hi < lo) {
        int T = hi;
        hi = lo;
        lo = T;
    }
    sort(a, lo0, lo);
    sort(a, lo == lo0 ? lo+1 : lo, hi0);
}

static void sort(int a[]) {
    sort(a, 0, a.length-1);
}

[edit] Delphi/Pascal Code

unit Unit2;

// INFO QuickSort zum Sortieren eines Array of Records oder Arrays
// INFO bzw. zum Sortieren einer "Tabelle"/"Matrix" nach einer Spalte
// INFO Aufruf erfolg mit quicksort(ARRAYbezeichung,Sortierrichtung)
// INFO Bei TRUE wird aufsteigend a..z und bei FALSE absteigend z..a sortiert

// VORRAUSSETZUNG es muss einen Datentyp vom Typ 'TMyArrayOne' geben !
// VORRAUSSETZUNG dieser kann ein "ARRAY of Records" oder "ARRAY of ARRAYs of 'DatentypXY'" sein

// VORRAUSSETZUNG ES MÜSSEN ZWEI STELLEN IM CODE ANGEPASST WERDEN, DIESE BEREICHE SIND DURCH --> GEKENNZEICHENT
// VORRAUSSETZUNG Das ist zueinem die Angabe der Spalte, nach der sortiert werden soll.
// VORRAUSSETZUNG Und zum anderen die Verknüpfung mit der Unit wo der Datentyp 'TMyArrayOne' deklariert wurde
interface

uses
    // --> Wo ist Datentyp 'TMyArrayOne' deklariert ???
    Unit1;

var aSortVergleich: array of Variant;
    procedure quicksort(var aUn2SortDaten0: TMyArrayOne; bSortierrichtung0:boolean);
    procedure quicksort_teil_a(var aUn2SortDaten1: TMyArrayOne; iLinksP1,iRechtsP1:integer);
    function  quicksort_teil_b(var aUn2SortDaten2: TMyArrayOne; iLinksP2,iRechtsP2:integer):integer;
    procedure quicksort_teil_c(var aUn2SortDaten3: TMyArrayOne; iDatensatzzeiger1, iDatensatzzeiger2: integer);

implementation

procedure quicksort(var aUn2SortDaten0: TMyArrayOne; bSortierrichtung0:boolean);
var iLinks0,iRechts0,i,j:integer;
begin
  // Der erste Datensatz LINKS im Array ist auf Position X
  iLinks0:=low(aUn2SortDaten0);
  // Der letze Datensatz RECHTS im Array ist auf Position Y
  iRechts0:=high(aUn2SortDaten0);
  // Aufbau des Vergleichsarrays
  setlength(aSortVergleich,length(aUn2SortDaten0));
  for i:=iLinks0 to iRechts0 do
    begin
  // ********************************************************* //
  // ** --> Angabe nach welcher Spalte sortiert werden soll ** //
      aSortVergleich[i]:=aUn2SortDaten0[i].sWort;
  // ********************************************************* //
    end;
    
  // ===========================================================
  // * BEGINN DER SORTIERUNG - KEINE ÄNDERUNGEN MEHR NOTWENDIG *

  //Durchführen der Sortierung
  quicksort_teil_a(aUn2SortDaten0, iLinks0, iRechts0);
  // es wurde jetzt von a..z sortiert, falls z..a gewünscht ist, geschieht das jetzt
  if not bSortierrichtung0 then
    begin
      repeat
        begin
          quicksort_teil_c(aUn2SortDaten0, iLinks0, iRechts0);
          iLinks0:=iLinks0+1;
          iRechts0:=iRechts0-1;
        end;
      until not (iLinks0 < iRechts0);
    end;
end;

// + Teilprozedure 1 von QuickSort +
procedure quicksort_teil_a(var aUn2SortDaten1: TMyArrayOne; iLinksP1,iRechtsP1:integer);
var iTeiler:integer;
begin
  if iLinksP1 < iRechtsP1 then
    begin
      iTeiler := quicksort_teil_b(aUn2SortDaten1, iLinksP1, iRechtsP1);
      quicksort_teil_a(aUn2SortDaten1, iLinksP1, iTeiler-1);
      quicksort_teil_a(aUn2SortDaten1, iTeiler+1, iRechtsP1);
    end;
end;

// + Teilprozedure 2 von QuickSort +
function quicksort_teil_b(var aUn2SortDaten2: TMyArrayOne; iLinksP2,iRechtsP2:integer):integer;
var iLinksTemp,iRechtsTemp:integer;
begin
     iLinksTemp := iLinksP2;
     // Starte mit j links vom Pivotelement
     iRechtsTemp := iRechtsP2 - 1;
     repeat
      begin
        // Suche von links ein Element, welches größer oder gleich dem Pivotelement ist
        while ((aSortVergleich[iLinksTemp] <= aSortVergleich[iRechtsP2]) and (iLinksTemp < iRechtsP2)) do  iLinksTemp:= iLinksTemp + 1;
        // Suche von rechts ein Element, welches kleiner oder gleich dem Pivotelement ist
        while ((aSortVergleich[iRechtsTemp] >= aSortVergleich[iRechtsP2]) and (iRechtsTemp > iLinksP2)) do iRechtsTemp:= iRechtsTemp - 1;
        if iLinksTemp < iRechtsTemp then quicksort_teil_c(aUn2SortDaten2, iLinksTemp, iRechtsTemp);
      end;
     until not(iLinksTemp < iRechtsTemp); // solange iLinks an iRechts nicht vorbeigelaufen ist
     // Tausche Pivotelement (daten[rechts]) mit neuer endgültigen Position (daten[i])
     quicksort_teil_c(aUn2SortDaten2, iLinksTemp, iRechtsP2);
     // gib die Position des Pivotelements zurück
     result:=iLinksTemp;
end;

// + Teilprozedure 3 von QuickSort +
procedure quicksort_teil_c(var aUn2SortDaten3: TMyArrayOne; iDatensatzzeiger1, iDatensatzzeiger2: integer);
var vHelp:Variant;
    iTempDatensatzanzahl:integer;
begin
  // Tauschen der beiden Vergleichswerte
  vHelp:=aSortVergleich[iDatensatzzeiger1];
  aSortVergleich[iDatensatzzeiger1]:=aSortVergleich[iDatensatzzeiger2];;
  aSortVergleich[iDatensatzzeiger2]:=vHelp;
  // Tauschen von zwei Datensätzen
  iTempDatensatzanzahl:=length(aUn2SortDaten3);
  setlength(aUn2SortDaten3,iTempDatensatzanzahl+1);
  aUn2SortDaten3[iTempDatensatzanzahl]:=aUn2SortDaten3[iDatensatzzeiger1];
  aUn2SortDaten3[iDatensatzzeiger1]:=aUn2SortDaten3[iDatensatzzeiger2];
  aUn2SortDaten3[iDatensatzzeiger2]:=aUn2SortDaten3[iTempDatensatzanzahl];
  setlength(aUn2SortDaten3,iTempDatensatzanzahl);
end;

// * ENDE VON QUICKSORT * //
//====================================================

end.

Noch ein Beispiel für die Deklaration des Records im anderen Unit

TMyRecordOne = record
    iZahl:integer;
    sWort:string;
    bEigenschaft:boolean;
  end;
  TMyArrayOne = array of TMyRecordOne;

var
  aDatenbank: TMyArrayOne;

Und der Aufruf der Sortierung dann im Code

quicksort(aDatenbank,True);
 procedure QuickSort(var A: array of Integer; iLO, iHi : integer);
 var
   Lo, Hi, Mid, T: Integer;
 begin
   Lo := iLo;
   Hi := iHi;
   Mid := A[(Lo + Hi) div 2];			//mid:=A[10]
   repeat
     while A[Lo] < Mid do Inc(Lo);
     while A[Hi] > Mid do Dec(Hi);
     if Lo <= Hi then
     begin
       T := A[Lo];
       A[Lo] := A[Hi];
       A[Hi] := T;
       Inc(Lo);			//increment  Lo:=Lo+1;
	  Dec(Hi);			//decrement  Hi:=Hi-1;
     end;
   until Lo > Hi;
   if Hi > iLo then QuickSort(A, iLo, Hi);
   if Lo < iHi then QuickSort(A, Lo, iHi);
 end;

[edit] VB.NET Code

 Private Sub QSort(ByVal list As Integer(), ByVal low As Integer, ByVal high As Integer)

        Dim pivote, left, right, temp As Integer
        left = low
        right = high - 1

        If low >= high Then Return
        pivote = list(high)
        Do
            While list(left) < pivote AndAlso left < right : left += 1 : End While
            While list(right) > pivote AndAlso right > left : right -= 1 : End While
            If list(left) > list(right) Then
                temp = list(left)
                list(left) = list(right)
                list(right) = temp
            Else
                Exit Do
            End If
        Loop

        temp = list(left)
        list(left) = list(high)
        list(high) = temp

        QSort(list, low, left - 1)
        QSort(list, left + 1, high)
    End Sub

[edit] VB Code

Option Explicit

Dim Result, I
Dim TestData(100)
const N = 100

Randomize
For I = 0 To N - 1
TestData(I) = ROUND(RND() * 32768)
Next

Sub Swap(byRef Array, first, second)
Dim t
t = Array(first)
Array(first) = Array(second)
Array(second) = t
End Sub

Sub QSort(byRef Array, low, hi)
Dim i, j, p
While low < hi
   p = Array(hi)
   i = low - 1
   For j = low To hi-1
    If Array(j) <= p Then
     i = i + 1
     Swap Array, i, j
    End If
   Next
   Swap Array, i+1, j
   QSort Array, low, i
   low = i + 2
Wend
End Sub

QSort TestData, 0, N - 1

For I = 0 To N - 1
Result = Result & TestData(I) & VbTab
Next

MsgBox(Result)

[edit] Perl Code

sub qsort {
  return () unless @_;
  return (qsort(grep { $_ < $_[0] } @_[1..$#_]), $_[0],
          qsort(grep { $_ >= $_[0] } @_[1..$#_]));
}

[edit] Prolog Code

append([], L, L).
append([H | L1], L2, [H | Result]) :- append(L1, L2, Result).

partition([], _, [], []).
partition([H | T], X, [H | Left], Right) :- H =< X, partition(T, X, Left, Right).
partition([H | T], X, Left, [H | Right]) :- H > X, partition(T, X, Left, Right).

qsort([],[]).
qsort([H | Tail], Sorted) :-
        partition(Tail, H, Left, Right),
        qsort(Left, SortedLeft),
        qsort(Right, SortedRight),
        append(SortedLeft, [H | SortedRight], Sorted).

[edit] Python Code

import random
qsort = lambda l:[] if not l else qsort([n for n in l if n<l[0]])+[n for n in l if n==l[0]]+qsort([n for n in l if n>l[0]])
aList = [random.randrange(1000) for i in xrange(10000)]
sortedList = qsort(aList)

[edit] Ruby Code

class Array
  def quicksort(list=self.dup)
    return list  if list.size <= 1
    pivot = list.delete_at(rand(list.size))
    left, right = list.partition { |e| e < pivot }
    quicksort(left) + [pivot] + quicksort(right)
  end
end

[edit] Haskell Code

qsort :: Ord a => [a] -> [a]
qsort []     = []
qsort (x:xs) = qsort [y | y <- xs, y < x] ++ [x] ++ qsort [y | y <- xs, y >= x]

[edit] Ada Code

procedure sort is       

type IArr is array (integer range <>) of integer;

procedure swap(X,Y : in out integer) is
      
   t:integer;
  begin
    t:=x;
    x:=y;
    y:=t;
  end swap;


procedure partition(arr: in out iarr; links, rechts:integer; pivot: out integer) is
         x: integer:= arr(links);
         i,j: integer;
      begin
         loop
            i:=links+1;
            while i <= arr'last and then arr(i) <= x loop
               i:=i+1;
            end loop;
            j:=rechts;
            while j>=arr'first and then arr(j) >x loop
               j:=j-1;
            end loop;
            if i< j and j>= arr'first and i <= arr'last then
               swap(arr(i),arr(j));
            end if;
            exit when i>j;
         
         end loop;
         arr(links):=arr(j);
         arr(j):=x;
         pivot:=j;
      end partition;
   
       procedure quicksortpart (arr: in out iarr; links , rechts :integer) is
         piv: integer;
      begin
         if links<rechts then
            partition(arr,links,rechts,piv);
            quicksortpart(arr,links,piv-1);
            quicksortpart(arr,piv+1,rechts);
         end if;
      end quicksortpart;
   
       procedure quicksort (arr:in out IArr) is
      	 
      	 
      begin
         quicksortpart(arr,arr'first,arr'last);
      end quicksort;

begin

null;
--- aufruf mit quicksort(Array);

end sort;
Personal tools