Review: the
parttion algorithm
of the
Quick Sort algorithm
- Input:
a sub array
A[s] .. A[e-1]:
| | | | | | | | | | | | | |
| 4 | | 5 | | 6 | | 3 | | 2 | | 1 | | 7 |
+---+ +---+ +---+ +---+ +---+ +---+ +---+
s s+1 ... e-1 e
|
- We select
A[s]
as pivot:
pivot = 4
| | | | | | | | | | | | | |
| 4 | | 5 | | 6 | | 3 | | 2 | | 1 | | 7 |
+---+ +---+ +---+ +---+ +---+ +---+ +---+
|
- Then we partition the
values into
2 subgroups:
(1) values
< pivot and
(2) values
≥ pivot:
| | | | | | | | | | | | | |
| 3 | | 2 | | 1 | | 4 | | 5 | | 6 | | 7 |
+---+ +---+ +---+ +---+ +---+ +---+ +---+
<------ group 1 ----> pivotLoc <------ group 2 ----->
|
- We must
return the
pivotLoc
|
A simplified
partition algorithm
- The partition( ) method
discussed in
Liang's text book
is a bit
complicated
- I have developed
and will present a
simpler
(but less efficient)
partition( ) method
- A
partitioning algorithm
maintains 2 half arrays:
a low half and a
high half:
(1) low half (2) high half
A[] = [ P L L L L L ? ? ? ? ? H H H H H ]
^ <-----------> ^ ^ <----------->
| < P | | >= P
pivot low high
|
- The
simplified
partitioning algorithm
only
compares
the pivot against
A[high]:
(1) low half (2) high half
A[] = [ P L L L L L ? ? ? ? X H H H H H ]
^ <-----------> ^ ^ <----------->
| < P | | >= P
pivot low high
| |
+-----------------------------+
compares: pivot <==> A[high]
|
|
A simplified
partition algorithm
A simplified
partition algorithm
:
we swap(X,Y) and
then increment low:
(1) low half (2) high half
A[] = [ P L L L L L X ? ? ? Y H H H H H ]
^ <--------------> ^ ^ <------------->
| < P | | >= P
pivot low high
| |
+-----------------------------+ A[high] (X) < pivot
|
|
Example of the
simplified
partition( ) algorithm
- Sample input:
partition(A, s, e):
index ---> s s+1 e-1 e
A[ ] [5, 4, 1, 7, 2, 9, 3, 6]
|
|
Example of the
simplified
partition( ) algorithm
- Initialize the
pivot:
partition(A, s, e):
index ---> s s+1 e-1 e
A[ ] [5, 4, 1, 7, 2, 9, 3, 6]
pivot = 5 (= A[s])
|
|
Example of the
simplified
partition( ) algorithm
- Initialize the
low index and
the high index:
partition(A, s, e):
index ---> s s+1 e-1 e
A[ ] [5, 4, 1, 7, 2, 9, 3, 6]
^ ^
| |
low = s+1 high = e-1
pivot = 5 (= A[s])
|
|
Example of the
simplified
partition( ) algorithm
Example of the
simplified
partition( ) algorithm
- Result:
partition(A, s, e):
index ---> s s+1 e-1 e
A[ ] [5, 4, 1, 7, 2, 9, 3, 6]
^ ^
| |
low = s+1 high
pivot = 5 (= A[s])
|
|
Example of the
simplified
partition( ) algorithm
Example of the
simplified
partition( ) algorithm
- Result:
partition(A, s, e):
index ---> s s+1 e-1 e
A[ ] [5, 3, 1, 7, 2, 9, 4, 6]
^ ^
| |
low high
pivot = 5 (= A[s])
|
|
Example of the
simplified
partition( ) algorithm
Example of the
simplified
partition( ) algorithm
- Result:
partition(A, s, e):
index ---> s s+1 e-1 e
A[ ] [5, 3, 4, 7, 2, 9, 1, 6]
^ ^
| |
low high
pivot = 5 (= A[s])
|
|
Example of the
simplified
partition( ) algorithm
Example of the
simplified
partition( ) algorithm
- Result:
partition(A, s, e):
index ---> s s+1 e-1 e
A[ ] [5, 3, 4, 1, 2, 9, 7, 6]
^ ^
| |
low high
pivot = 5 (= A[s])
|
|
Example of the
simplified
partition( ) algorithm
Example of the
simplified
partition( ) algorithm
- Result:
partition(A, s, e):
index ---> s s+1 e-1 e
A[ ] [5, 3, 4, 1, 2, 9, 7, 6]
^ ^
| |
low high
pivot = 5 (= A[s])
|
|
Example of the
simplified
partition( ) algorithm
Example of the
simplified
partition( ) algorithm
Example of the
simplified
partition( ) algorithm
- To put the
pivot in its
correct location,
we do
exch(A, s, high):
partition(A, s, e):
index ---> s s+1 e-1 e
A[ ] [5, 3, 4, 1, 2, 9, 7, 6]
^ ^ ^
| | |
| high low
| |
+-------------------+
swap
pivot = 5 (= A[s])
|
|
Example of the
simplified
partition( ) algorithm
The
simplified
partition( ) algorithm
The simplified
partition( ) algorithm:
// partition(A, s, e): partition A[s]..A[e-1] using pivot A[s]
public static <T extends Comparable<T>> int partition(T[] A, int s, int e)
{
T pivot = A[s];
int low = s+1, high = e-1;
while (low <= high)
{
if ( A[high].compareTo(pivot) >= 0 )
{
high--;
}
else
{
exch(A, low, high);
low++;
}
}
exch(A, s, high);
return high;
}
|
The
simplified
partition( ) algorithm
Select
pivot = A[s]:
// partition(A, s, e): partition A[s]..A[e-1] using pivot A[s]
public static <T extends Comparable<T>> int partition(T[] A, int s, int e)
{
T pivot = A[s];
int low = s+1, high = e-1;
while (low <= high)
{
if ( A[high].compareTo(pivot) >= 0 )
{
high--;
}
else
{
exch(A, low, high);
low++;
}
}
exch(A, s, high);
return high;
}
|
The
simplified
partition( ) algorithm
Initialize the
low and
high
indixes:
// partition(A, s, e): partition A[s]..A[e-1] using pivot A[s]
public static <T extends Comparable<T>> int partition(T[] A, int s, int e)
{
T pivot = A[s];
int low = s+1, high = e-1;
while (low <= high)
{
if ( A[high].compareTo(pivot) >= 0 )
{
high--;
}
else
{
exch(A, low, high);
low++;
}
}
exch(A, s, high);
return high;
}
|
The
simplified
partition( ) algorithm
As long as low ≤ high
(i.e., have not crossed),
we compare
A[high] against the
pivot:
// partition(A, s, e): partition A[s]..A[e-1] using pivot A[s]
public static <T extends Comparable<T>> int partition(T[] A, int s, int e)
{
T pivot = A[s];
int low = s+1, high = e-1;
while (low <= high)
{
if ( A[high].compareTo(pivot) >= 0 )
{
high--;
}
else
{
exch(A, low, high);
low++;
}
}
exch(A, s, high);
return high;
}
|
The
simplified
partition( ) algorithm
If
A[high] >= pivot,
then
A[high] belongs to
the high portion and
we
decrement high
:
// partition(A, s, e): partition A[s]..A[e-1] using pivot A[s]
public static <T extends Comparable<T>> int partition(T[] A, int s, int e)
{
T pivot = A[s];
int low = s+1, high = e-1;
while (low <= high)
{
if ( A[high].compareTo(pivot) >= 0 )
{
high--;
}
else
{
exch(A, low, high);
low++;
}
}
exch(A, s, high);
return high;
}
|
The
simplified
partition( ) algorithm
Otherwise
A[high] belongs to
the low portion and
we (1)
swap(A[low],A[high])
and
(2)
increment low
:
// partition(A, s, e): partition A[s]..A[e-1] using pivot A[s]
public static <T extends Comparable<T>> int partition(T[] A, int s, int e)
{
T pivot = A[s];
int low = s+1, high = e-1;
while (low <= high)
{
if ( A[high].compareTo(pivot) >= 0 )
{
high--;
}
else
{
exch(A, low, high);
low++;
}
}
exch(A, s, high);
return high;
}
|
The
simplified
partition( ) algorithm
Finally,
we (1)
swap(pivot,A[high])
and
(2) return
high
:
// partition(A, s, e): partition A[s]..A[e-1] using pivot A[s]
public static <T extends Comparable<T>> int partition(T[] A, int s, int e)
{
T pivot = A[s];
int low = s+1, high = e-1;
while (low <= high)
{
if ( A[high].compareTo(pivot) >= 0 )
{
high--;
}
else
{
exch(A, low, high);
low++;
}
}
exch(A, s, high); // A[s] = pivot
return high;
}
|
Demo program
// Sort integers
public static void main(String[] args)
{
Integer[] A = { 5, 4, 1, 7, 2, 9, 3, 6 };
System.out.println("Input = " + Arrays.toString(A) + "\n");
QuickSort.sort(A, 0, A.length);
System.out.println("Output = " + Arrays.toString(A) + "\n");
}
// Sort strings
public static void main(String[] args)
{
String[] A = { "klm", "xyz", "abc", "uvw", "qrs", "fgh", "bcd", "mno"};
System.out.println("Input = " + Arrays.toString(A) + "\n");
QuickSort.sort(A, 0, A.length);
System.out.println("Output = " + Arrays.toString(A) + "\n");
}
|
DEMO:
demo/14-sort/14-quick-sort/Demo.java +
Demo2.java
The
partition algorithm in Liang's
text book
The partition( ) method
discussed in
Liang's text book
is as follows:
- Initialize:
(1)
pivot = A[s],
(2)
low = s+1 and
(3)
high = s-1
A[] = [ 5, 3, 4, 7, 8, 1, 2, 6, 9 ]
^ ^
| |
low high
|
- Starting at
index low,
find
forward the
first element that
is > pivot:
A[] = [ 5, 3, 4, 7, 8, 1, 2, 6, 9 ]
^ ^
| |
low high
|
- Starting at
index high,
find
backward the
first element that
is < pivot:
A[] = [ 5, 3, 4, 7, 8, 1, 2, 6, 9 ]
^ ^
| |
low high
|
- Swap
A[low] <--> A[high]
(1 swap will move
2 values in their correct places)
|
The
partition algorithm in
Liang's
text book
public static int partition(int[] list, int first, int last)
{
int pivot = list[first]; // Choose the first element as the pivot
int low = first + 1; // Index for forward search
int high = last - 1; // Index for backward search
while (low < high)
{
// Search forward from left
while (low <= high && list[low] <= pivot)
low++;
// Search backward from right
while (low <= high && list[high] > pivot)
high--;
// Swap two elements in the list
if (low < high)
{
int temp = list[high];
list[high] = list[low];
list[low] = temp;
}
}
// Adjust high to find the border
while (high > first && list[high] >= pivot)
high--;
// Swap pivot with list[high]
if (pivot > list[high])
{
list[first] = list[high];
list[high] = pivot;
return high;
}
else
{
return first; // Pivot was the smallest element...
}
}
|
Additional properties of
Quick Sort algorithm
- Recall:
In-place
- A sorting algorithm is
in-place
if it
does not
require
another array
to execute the algorithm
|
The Quick Sort
algorithm is
an
in-place
sorting algorithm
- Recall:
Stable:
- A sorting algorithm
is
stable
if
it preserves
the
relative order
of equal keys in the array
|
The Quick Sort
algorithm is
not stable
Example: partition( ) will
swap(9,4)
and re-arange the
ordering of the
4's
A[] = [ 5 1 9 .. .. .. .. 4 4 8 ]
^ ^
| |
low high
A[] = [ 5 1 4 .. .. .. .. 4 9 8 ]
|
|
❮
❯