- Insert the elements one by one with a series of
insert(e)
operations - Remove the elements in sorted order with a series of
removeMin()
operations
- Inserting elements into a PQ (implemented with an unsorted list) without taking care of the order;
- Removing an element from the PQ needs a search
- Inserting elements into a PQ (implemented with a sorted list) while taking care of the order;
- Removing an element at the front
- Inserting elements into a PQ (implemented with a heap) while keeping the heap-order;
- Removing an element at the root of the heap (a downheap maybe necessary)
- Divide-and-conquer is a general algorithm design paradigm:
- Divide: divide the input data
S
in two disjoint subsetsS_1
andS_2
- Recur: solve the subproblems associated with
S_1
andS_2
- Conquer: combine the solutions for
S_1
andS_2
into a solution forS
- Divide: divide the input data
- The base case for the recursion are subproblems of size
0
or1
-
Merge-sort is a sorting algorithm based on the divide-and-conquer paradigm
-
Like heap-sort
- It uses a comparator
- It has
O(n log n)
running time
-
Unlike heap-sort
-
It does not use an auxiliary priority queue
-
It accesses data in a sequential manner (suitable to sort data on a disk)
-
Merge-sort on an input sequence
S
withn
elements consists of three steps:- Divide: partition
S
into two sequencesS_1
andS_2
of aboutn/2
elements each - Recur: recursively sort
S_1
andS_2
- Conquer: merge
S_1
andS_2
into a unique sorted sequence
- Divide: partition
Algorithm mergeSort(S, C)
Input sequence S with n
elements, comparator C
Output sequence S sorted
according to C
if S.size() > 1
(S1, S2) ← partition(S, n/2)
mergeSort(S1, C)
mergeSort(S2, C)
else:
S ← merge(S1, S2)
- The conquer step of merge-sort consists of merging two sorted sequences
A
andB
into a sorted sequenceS
containing the union of the elements ofA
andB
- Merging two sorted sequences, each with
n/2
elements and implemented by means of a doubly linked list, takesO(n)
time
Algorithm merge(A, B)
Input sequences A and B with n/2 elements each
Output sorted sequence of A È B
S ← empty sequence
while (not A.empty()) and (not B.empty())
if A.front() < B.front()
S.addBack(A.front());
A.eraseFront();
else
S.addBack(B.front());
B.eraseFront();
while not A.empty()
S.addBack(A.front());
A.eraseFront();
while not B.empty()
S.addBack(B.front());
B.eraseFront();
return S
- An execution of merge-sort is depicted by a binary tree
- Each node represents are cursive call of merge-sort and stores
- Unsorted sequence before the execution and its partition
- Sorted sequence at the end of the execution
- The root is the initial call
- The leaves are calls on subsequences of size
0
or1
- The height
h
of the merge-sort tree isO(logn)
- At each recursive call we divide in half the sequence,
- The overall amount or work done at the nodes of depth
i
isO(n)
- We partition and merge
2^i
sequences of sizen/2^i
- We make
2^(i+1)
recursive calls
- We partition and merge
- Thus, the total running time of merge-sort is
O(nlogn)
- Quick-sort is a randomized sorting algorithm based on the divide-and-conquer paradigm:
- Divide: pick a random element
x
(called pivot) and partitionS
intoL
elements less thanx
E
elements equalx
G
elements greater thanx
- Recur: sort
L
andG
- Conquer: join
L
,E
andG
- Divide: pick a random element
- We partition an input sequenceas follows:
- We remove, in turn, each element
y
fromS
and - We insert
y
intoL
,E
orG
, depending on the result of the comparison with the pivotx
- We remove, in turn, each element
- Each insertion and removal is at the beginning or at the end of a sequence, and hence takes
O(1)
time - Thus, the partition step of quick-sort takes
O(n)
time
Algorithm partition(S, p)
Input sequence S, position p of pivot
Output subsequences L, E, G of the elements of S less than, equal to, or greater than the pivot, respectively
L, E, G ← empty sequences
x ← S.erase(p)
while not S.empty()
y ← S.eraseFront()
if y < x
L.insertBack(y)
else if y = x
E.insertBack(y)
else // y > x
G.insertBack(y)
return L, E, G
- An execution of quick-sort is depicted by a binary tree
- Each node represents are cursive call of quick-sort and stores
- Unsorted sequence before the execution and its pivot
- Sorted sequence at the end of the execution
- The root is the initial call
- The leaves are call son subsequences of size
0
or1
- Each node represents are cursive call of quick-sort and stores
- The worst case for quick-sort occurs when the pivot is the unique minimum or maximum element
- One of
L
andG
has sizen-1
and the other has size0
- The running time is proportional to the sum
n + (n - 1) + ... + 2 + 1
- Thus, the worst-case running time of quick-sort is
O(n^2)
- Consider a recursive call of quick-sort on a sequence of sizes
- Good call: the sizes of
L
andG
are each less than3s/4
- Bad call: one of
L
andG
has size greater than3s/4
- Good call: the sizes of
-
A call is good with probability
1/2
-
The expected height of the quick-sort tree is
O(logn)
-
The amount or work done at the nodes of the same depth is
O(n)
-
Thus, the expected running time of quick-sort is
O(nlogn)
- Quick-sort can be implemented to run in-place
- In the partition step, we use replace operations to rearrange the elements of the input sequence such that
- The elements less than the pivot have rank less than
h
- The elements equal to the pivo thave rank between h and
k
- The elements greater than the pivot have rank greater than
k
- The elements less than the pivot have rank less than
- The recursive calls consider
- Elements with rank less than
h
- Elements with rank greater than
k
- Elements with rank less than
Algorithm inPlaceQuickSort(S, l, r)
Input sequence S, ranks l and r
Output sequence S with the elements of rank between l and r rearranged in increasing order
if l >= r
return
i ← a random integer between l and r
x ← S.elemAtRank(i)
(h, k) ← inPlacePartition(x)
inPlaceQuickSort(S, l, h - 1)
inPlaceQuickSort(S, k + 1, r)
-
Send pivot to the end of the sequence
-
Repeat until
l
andr
cross:- Scan
l
to the right until finding an element>=x
- Scan
r
to the left until finding an element<x
- Swap elements at indices
l
andr
- Scan
-
Then swap the element at
l
and at the end (atx
)