Chapter 7 Sorting

See also here

Preliminaries

void X_sort(ElementType A[], int N);

Insertion Sort

void InsertionSort(ElementType A[], int N){
int j, p;
ElementType tmp;
for(p = 1; p < N; ++p){
tmp = A[p];
for(j = p; j > 0 && A[j - 1] > tmp; --j){
A[j] = A[j - 1];
}
A[j] = tmp;
}
}

T(N)=O(N)O(N2)T(N)=O(N)\sim O(N^2)

Lower Bound for Simple Sorting Algorithm

Inversion: ordered pair (i, j) that i < j and A[i] > A[j]

For simple sorting algorithm, one swap operation removes one inversion, so that T(N,I)=O(I+N)T(N,I)=O(I + N)

Theorem

Average inversions in an random array: I=N(N1)/4I=N(N-1)/4

T(N)=Ω(N2)T(N)=\Omega(N^2)

Swap elements that are far apart could remove some inversions at once

Shellsort

多次间隔的插入排序

  • Define an increment sequence h1=1<h2<<hth_1=1<h_2<…<h_t
  • Define an hkh_k-sort at each phase for k=t,t1,,1k=t,t-1,…,1

hk1h_{k-1}-sort remains hkh_k-sort

Shellsort is an in-place but not stability sorting algorithm
Insertion sort is in-place and stability sorting algorithm

Shell’s Increment Sequence

ht=floor(N/2),hk=floor(hk+1/2):1,2,4,8,h_t=floor(N/2),h_k=floor(h_{k+1}/2):1,2,4,8,…

// code omitted

Twst(N)=O(N2)T_{wst}(N)=O(N^2)

Pairs of increments are necessarily relatively prime

Hibbard’s Increment Sequence

hk=2k1:1,3,7,15,h_k=2^k-1:1,3,7,15,…

Twst(N)=O(N3/2)>O(NlogN)T_{wst}(N)=O(N^{3/2})>O(N\log N)
Tavg=O(N5/4)T_{avg}=O(N^{5/4})

Sedgewick’s Increment Sequence

hk=9×4i9×2i+1 or 4i3×2i+1h_k=9\times4^i-9\times2^i+1\ \mathrm{or}\ 4^i-3\times2^i+1

Twst(N)=O(N4/3)T_{wst}(N)=O(N^{4/3})
Tavg(N)=O(N7/6)T_{avg}(N)=O(N^{7/6})

Heapsort

in-place but not stable

Implement 1

{
BuildHeap(H);
for(i = 0; i < N; ++i)
TmpH[i] = DeleteMin(H);
for(i = 0; i < N; ++i)
H[i] = TmpH[i];
}

T(N)=NlogNT(N)=N\log N
S(N)=2NS(N)=2N

Implement 2

See also

void percolateDown(ElemType* base, size_t begin, size_t end,int (*ptrCompFunc)(const ElemType* x, const ElemType* y)){  
size_t parent, lChild, rChild;
parent = begin, lChild = 2 * parent + 1, rChild = lChild + 1;
while(parent < end){
size_t max = parent;
if(lChild < end && !(*ptrCompFunc)(base + lChild, base + max))
max = lChild;
if(rChild < end && !(*ptrCompFunc)(base + rChild, base + max))
max = rChild;
if(parent == max) break;
swap(base + parent, base + max);
parent = max, lChild = 2 * parent + 1, rChild = lChild + 1;
}
}

// main sort
void heapSort(ElemType* base, size_t n, int (*ptrCompFunc)(const ElemType* x, const ElemType* y)){
for(size_t i = n / 2 - 1; ; --i){
percolateDown(base, i, n, ptrCompFunc);
if(i == 0) break;
}
for(size_t i = n - 1; ; --i){
swap(base, base + i);
percolateDown(base, 0, i, ptrCompFunc);
if(i == 0) break;
}
}

Tavg(N)=2NlogNO(NloglogN)T_{avg}(N)=2N\log N-O(N\log\log N)

Mergesort

See Also

Quicksort

the fastest (not) sorting algorithm

See also

Implementation

Tbst(N)=O(NlogN)T_{bst}(N)=O(N\log N)

Twst(N)=O(N2)T_{wst}(N)=O(N^2)

Picking the Pivot

  1. wrong way

Pivot = A[0]

  1. safe maneuver

Pivot = random select from A[]

random number generation is expensive

  1. median-of-three partitioning

Pivot = median(left, center, right)