Sie sind auf Seite 1von 62

Quicksort Algorithm

Given an array of n elements (e.g., integers):


 If array only contains one element, return
 Else
◦ pick one element to use as pivot.
◦ Partition elements into two sub-arrays:
 Elements less than or equal to pivot
 Elements greater than pivot
◦ Quicksort two sub-arrays
◦ Return results
Example
We are given array of n integers to sort:
40 20 10 80 60 50 7 30 100
Pick Pivot Element
There are a number of ways to pick the pivot element. In
this example, we will use the first element in the array:

40 20 10 80 60 50 7 30 100
Partitioning Array
Given a pivot, partition the elements of the array
such that the resulting array consists of:
1. One sub-array that contains elements >= pivot
2. Another sub-array that contains elements < pivot

The sub-arrays are stored in the original data array.

Partitioning loops through, swapping elements


below/above pivot.
pivot_index = 0 40 20 10 80 60 50 7 30 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

too_big_index too_small_index
1. While data[too_big_index] <= data[pivot]
++too_big_index

pivot_index = 0 40 20 10 80 60 50 7 30 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

too_big_index too_small_index
1. While data[too_big_index] <= data[pivot]
++too_big_index

pivot_index = 0 40 20 10 80 60 50 7 30 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

too_big_index too_small_index
1. While data[too_big_index] <= data[pivot]
++too_big_index

pivot_index = 0 40 20 10 80 60 50 7 30 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

too_big_index too_small_index
1. While data[too_big_index] <= data[pivot]
++too_big_index
2. While data[too_small_index] > data[pivot]
--too_small_index

pivot_index = 0 40 20 10 80 60 50 7 30 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

too_big_index too_small_index
1. While data[too_big_index] <= data[pivot]
++too_big_index
2. While data[too_small_index] > data[pivot]
--too_small_index

pivot_index = 0 40 20 10 80 60 50 7 30 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

too_big_index too_small_index
1. While data[too_big_index] <= data[pivot]
++too_big_index
2. While data[too_small_index] > data[pivot]
--too_small_index
3. If too_big_index < too_small_index
swap data[too_big_index] and data[too_small_index]

pivot_index = 0 40 20 10 80 60 50 7 30 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

too_big_index too_small_index
1. While data[too_big_index] <= data[pivot]
++too_big_index
2. While data[too_small_index] > data[pivot]
--too_small_index
3. If too_big_index < too_small_index
swap data[too_big_index] and data[too_small_index]

pivot_index = 0 40 20 10 30 60 50 7 80 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

too_big_index too_small_index
1. While data[too_big_index] <= data[pivot]
++too_big_index
2. While data[too_small_index] > data[pivot]
--too_small_index
3. If too_big_index < too_small_index
swap data[too_big_index] and data[too_small_index]
4. While too_small_index > too_big_index, go to 1.

pivot_index = 0 40 20 10 30 60 50 7 80 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

too_big_index too_small_index
1. While data[too_big_index] <= data[pivot]
++too_big_index
2. While data[too_small_index] > data[pivot]
--too_small_index
3. If too_big_index < too_small_index
swap data[too_big_index] and data[too_small_index]
4. While too_small_index > too_big_index, go to 1.

pivot_index = 0 40 20 10 30 60 50 7 80 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

too_big_index too_small_index
1. While data[too_big_index] <= data[pivot]
++too_big_index
2. While data[too_small_index] > data[pivot]
--too_small_index
3. If too_big_index < too_small_index
swap data[too_big_index] and data[too_small_index]
4. While too_small_index > too_big_index, go to 1.

pivot_index = 0 40 20 10 30 60 50 7 80 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

too_big_index too_small_index
1. While data[too_big_index] <= data[pivot]
++too_big_index
2. While data[too_small_index] > data[pivot]
--too_small_index
3. If too_big_index < too_small_index
swap data[too_big_index] and data[too_small_index]
4. While too_small_index > too_big_index, go to 1.

pivot_index = 0 40 20 10 30 60 50 7 80 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

too_big_index too_small_index
1. While data[too_big_index] <= data[pivot]
++too_big_index
2. While data[too_small_index] > data[pivot]
--too_small_index
3. If too_big_index < too_small_index
swap data[too_big_index] and data[too_small_index]
4. While too_small_index > too_big_index, go to 1.

pivot_index = 0 40 20 10 30 60 50 7 80 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

too_big_index too_small_index
1. While data[too_big_index] <= data[pivot]
++too_big_index
2. While data[too_small_index] > data[pivot]
--too_small_index
3. If too_big_index < too_small_index
swap data[too_big_index] and data[too_small_index]
4. While too_small_index > too_big_index, go to 1.

pivot_index = 0 40 20 10 30 60 50 7 80 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

too_big_index too_small_index
1. While data[too_big_index] <= data[pivot]
++too_big_index
2. While data[too_small_index] > data[pivot]
--too_small_index
3. If too_big_index < too_small_index
swap data[too_big_index] and data[too_small_index]
4. While too_small_index > too_big_index, go to 1.

pivot_index = 0 40 20 10 30 7 50 60 80 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

too_big_index too_small_index
1. While data[too_big_index] <= data[pivot]
++too_big_index
2. While data[too_small_index] > data[pivot]
--too_small_index
3. If too_big_index < too_small_index
swap data[too_big_index] and data[too_small_index]
4. While too_small_index > too_big_index, go to 1.

pivot_index = 0 40 20 10 30 7 50 60 80 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

too_big_index too_small_index
1. While data[too_big_index] <= data[pivot]
++too_big_index
2. While data[too_small_index] > data[pivot]
--too_small_index
3. If too_big_index < too_small_index
swap data[too_big_index] and data[too_small_index]
4. While too_small_index > too_big_index, go to 1.

pivot_index = 0 40 20 10 30 7 50 60 80 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

too_big_index too_small_index
1. While data[too_big_index] <= data[pivot]
++too_big_index
2. While data[too_small_index] > data[pivot]
--too_small_index
3. If too_big_index < too_small_index
swap data[too_big_index] and data[too_small_index]
4. While too_small_index > too_big_index, go to 1.

pivot_index = 0 40 20 10 30 7 50 60 80 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

too_big_index too_small_index
1. While data[too_big_index] <= data[pivot]
++too_big_index
2. While data[too_small_index] > data[pivot]
--too_small_index
3. If too_big_index < too_small_index
swap data[too_big_index] and data[too_small_index]
4. While too_small_index > too_big_index, go to 1.

pivot_index = 0 40 20 10 30 7 50 60 80 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

too_big_index too_small_index
1. While data[too_big_index] <= data[pivot]
++too_big_index
2. While data[too_small_index] > data[pivot]
--too_small_index
3. If too_big_index < too_small_index
swap data[too_big_index] and data[too_small_index]
4. While too_small_index > too_big_index, go to 1.

pivot_index = 0 40 20 10 30 7 50 60 80 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

too_big_index too_small_index
1. While data[too_big_index] <= data[pivot]
++too_big_index
2. While data[too_small_index] > data[pivot]
--too_small_index
3. If too_big_index < too_small_index
swap data[too_big_index] and data[too_small_index]
4. While too_small_index > too_big_index, go to 1.

pivot_index = 0 40 20 10 30 7 50 60 80 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

too_big_index too_small_index
1. While data[too_big_index] <= data[pivot]
++too_big_index
2. While data[too_small_index] > data[pivot]
--too_small_index
3. If too_big_index < too_small_index
swap data[too_big_index] and data[too_small_index]
4. While too_small_index > too_big_index, go to 1.

pivot_index = 0 40 20 10 30 7 50 60 80 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

too_big_index too_small_index
1. While data[too_big_index] <= data[pivot]
++too_big_index
2. While data[too_small_index] > data[pivot]
--too_small_index
3. If too_big_index < too_small_index
swap data[too_big_index] and data[too_small_index]
4. While too_small_index > too_big_index, go to 1.

pivot_index = 0 40 20 10 30 7 50 60 80 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

too_big_index too_small_index
1. While data[too_big_index] <= data[pivot]
++too_big_index
2. While data[too_small_index] > data[pivot]
--too_small_index
3. If too_big_index < too_small_index
swap data[too_big_index] and data[too_small_index]
4. While too_small_index > too_big_index, go to 1.
5. Swap data[too_small_index] and data[pivot_index]

pivot_index = 0 40 20 10 30 7 50 60 80 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

too_big_index too_small_index
1. While data[too_big_index] <= data[pivot]
++too_big_index
2. While data[too_small_index] > data[pivot]
--too_small_index
3. If too_big_index < too_small_index
swap data[too_big_index] and data[too_small_index]
4. While too_small_index > too_big_index, go to 1.
5. Swap data[too_small_index] and data[pivot_index]

pivot_index = 4 7 20 10 30 40 50 60 80 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

too_big_index too_small_index
Partition Result

7 20 10 30 40 50 60 80 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

<= data[pivot] > data[pivot]


Recursion: Quicksort Sub-arrays

7 20 10 30 40 50 60 80 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

<= data[pivot] > data[pivot]


Quicksort Analysis
 Assume that keys are random, uniformly
distributed.
 What is best case running time?
Quicksort Analysis
 Assume that keys are random, uniformly
distributed.
 What is best case running time?
◦ Recursion:
1. Partition splits array in two sub-arrays of size
n/2
2. Quicksort each sub-array
Quicksort Analysis
 Assume that keys are random, uniformly
distributed.
 What is best case running time?
◦ Recursion:
1. Partition splits array in two sub-arrays of size
n/2
2. Quicksort each sub-array
◦ Depth of recursion tree?
Quicksort Analysis
 Assume that keys are random, uniformly
distributed.
 What is best case running time?
◦ Recursion:
1. Partition splits array in two sub-arrays of size
n/2
2. Quicksort each sub-array
◦ Depth of recursion tree? O(log2n)
Quicksort Analysis
 Assume that keys are random, uniformly
distributed.
 What is best case running time?
◦ Recursion:
1. Partition splits array in two sub-arrays of size
n/2
2. Quicksort each sub-array
◦ Depth of recursion tree? O(log2n)
◦ Number of accesses in partition?
Quicksort Analysis
 Assume that keys are random, uniformly
distributed.
 What is best case running time?
◦ Recursion:
1. Partition splits array in two sub-arrays of size
n/2
2. Quicksort each sub-array
◦ Depth of recursion tree? O(log2n)
◦ Number of accesses in partition? O(n)
Quicksort Analysis
 Assume that keys are random, uniformly
distributed.
 Best case running time: O(n log2n)
Quicksort Analysis
 Assume that keys are random, uniformly
distributed.
 Best case running time: O(n log2n)
 Worst case running time?
Quicksort: Worst Case
 Assume first element is chosen as pivot.
 Assume we get array that is already in
order:

pivot_index = 0 2 4 10 12 13 50 57 63 100
[0] [1] [2] [3] [4] [5] [6] [7] [8]

too_big_index too_small_index
Quicksort Analysis
 Assume that keys are random, uniformly
distributed.
 Best case running time: O(n log2n)
 Worst case running time?
◦ Recursion:
1. Partition splits array in two sub-arrays:
• one sub-array of size 0
• the other sub-array of size n-1
2. Quicksort each sub-array
◦ Depth of recursion tree?
Quicksort Analysis
 Assume that keys are random, uniformly
distributed.
 Best case running time: O(n log2n)
 Worst case running time?
◦ Recursion:
1. Partition splits array in two sub-arrays:
• one sub-array of size 0
• the other sub-array of size n-1
2. Quicksort each sub-array
◦ Depth of recursion tree? O(n)
Quicksort Analysis
 Assume that keys are random, uniformly
distributed.
 Best case running time: O(n log2n)
 Worst case running time?
◦ Recursion:
1. Partition splits array in two sub-arrays:
• one sub-array of size 0
• the other sub-array of size n-1
2. Quicksort each sub-array
◦ Depth of recursion tree? O(n)
◦ Number of accesses per partition?
Quicksort Analysis
 Assume that keys are random, uniformly
distributed.
 Best case running time: O(n log2n)
 Worst case running time?
◦ Recursion:
1. Partition splits array in two sub-arrays:
• one sub-array of size 0
• the other sub-array of size n-1
2. Quicksort each sub-array
◦ Depth of recursion tree? O(n)
◦ Number of accesses per partition? O(n)
Quicksort Analysis
 Assume that keys are random, uniformly
distributed.
 Best case running time: O(n log2n)
 Worst case running time: O(n2)!!!
Quicksort Analysis
 Assume that keys are random, uniformly
distributed.
 Best case running time: O(n log2n)
 Worst case running time: O(n2)!!!
 What can we do to avoid worst case?
Improved Pivot Selection
Pick median value of three elements from data
array:
data[0], data[n/2], and data[n-1].

Use this median value as pivot.


Radix Sort
 How did IBM get rich originally?
 Answer: punched card readers for census
tabulation in early 1900’s.
◦ In particular, a card sorter that could sort cards
into different bins
 Each column can be punched in 12 places
 (Decimal digits use only 10 places!)
◦ Problem: only one column can be sorted on
at a time
Radix Sort: Example
A: 136 487 358 469 570 247 598 639 205 609

(a) Input list

Q0: 570

Q1:

Q2:

Q3:

Q4:

Q5: 205

Q6: 136

Q7: 487 247

Q8: 358 598

Q9: 469 639 609


(b) Distribution of elements into 10 auxiliary arrays

A: 570 205 136 487 247 358 598 469 639 609

(c) Combining all elements from auxiliary arrays to A


Radix Sort: Example
A: 570 205 136 487 247 358 598 469 639 609

Q0: 205 609

Q1:

Q2:

Q3: 136 639

Q4: 247

Q5: 358

Q6: 469

Q7: 570

Q8: 487

Q9: 598
(d) Distribution of elements into 10 auxiliary arrays in Pass 2

A: 205 609 136 639 247 358 469 570 487 598
Radix Sort: Example
A: 205 609 136 639 247 358 469 570 487 598

(e) Combining all elements from auxiliary arrays to A

Q0:

Q1: 136

Q2: 205 247

Q3: 358

Q4: 469 487

Q5: 570 598

Q6: 609 639

Q7:

Q8:

Q9:
(f) Distribution of elements into 10 auxiliary arrays in Pass 3

A: 136 205 247 358 469 487 570 598 609 639

(g) Combining all elements from auxiliary arrays to A


Radix sort: another application of the Queue ADT
Sorting methods which utilize digital properties of the numbers (keys) in the
sorting process are called radix sorts.

Example. Consider the list 459 254 472 534 649 239 432 654 477

Step 1: ordering wrt ones Step 2: ordering wrt tens Step 3: ordering wrt hundreds

0 0 0
1 1 1
2 472 432 2 2 239 254
3 3 432 534 239 3
4 254 534 654 4 649 4 432 459 472 477
5 5 254 654 459 5 534
6 6 6 649 654
7 477 7 472 477 7
8 8 8
9 459 649 239 9 9

After step 1: 472 432 254 534 654 477 459 649 239
After step 2: 432 534 239 649 254 654 459 472 477
Radix Sort: the algorithm (cont.)
Here is a more detailed pseudo code description of the radix sort:

Input: A queue Q of N items


Output: Q sorted in ascending order
Algorithm RadixSort (Q, N):
digit := 1
while StillNotZero (digit) do {
for (i := 1 to 10) do {
create (sublist[i]) }
while (! empty Q) do {
dequeue (Q, item)
pile := getPile (item, digit) + 1 O(N)
enqueue (sublist[pile], item) swaps this outer loop will execute
} “digit” times
reinitialize (Q)
for (j :=1 to 10) do {
while (! empty sublist(j)) do {
dequeue (sublist[j], item) O(N)
enqueue (Q, item) } swaps
}
digit := digit * 10
Sparse Matrices

sparse … many elements are zero


dense … few elements are zero
Example of Sparse Matrices
diagonal
tridiagonal
lower triangular (?)

These are structured sparse matrices.


May be mapped into a 1D array so that a mapping function
can be used to locate an element.
Single Linear List Example

00304
00570 list =
00000 row 1 1 2 2 4 4
02600 column 3 5 3 4 2 3
value 3 4 5 7 2 6
Array Linear List Representation
row 1 1 2 2 4 4
list = column 3 5 3 4 2 3
value 3 4 5 7 2 6

element 0 1 2 3 4 5
row 1 1 2 2 4 4
column 3 5 3 4 2 3
value 3 4 5 7 2 6
Chain Representation

Node structure.

row col
valu nex
e t
Single Chain
row 1 1 2 2 4 4
list = column 3 5 3 4 2 3
value 3 4 5 7 2 6

1 3 1 5 2 3 2 4 4 2 4 3
3 4 5 7 2 6 null

firstNode
One Linear List Per Row

00304 row1 = [(3, 3), (5,4)]


00570 row2 = [(3,5), (4,7)]
00000
row3 = [ ]
02600
row4 = [(2,2), (3,6)]
Array of Row Chains
Node structure.

nex
colt value
Array of Row Chains
null
3 3 5 4
00304
00570 null
3 5 4 7
00000
02600
null

null
2 2 3 6
row[ ]