How fast can we sort?
All the sorting algorithms we have seen so far are comparison sorts
: only use comparisons to determine the relative order of elements.
- E.g., insertion sort, merge sort, quicksort, heapsort.
- The best worst-case running time that we’ve seen for comparison sorting is
O(n lgn).
Decision-tree example(决策树)
以第一个节点为例,1:2,即a1与a2进行比较,若a1<=a2,则走左子树;a1>a2,则走右子树。
Decision-tree model
A decision tree can model the execution of any comparison sort: - One tree for each input size n.
- View the algorithm as splitting whenever it compares two elements.(当比较两个元素时,将该算法视为分割)
- The tree contains the comparisons along all possible instruction traces.(树包含了所有可能的指令轨迹上的比较)
- The running time of the algorithm = the length of the path taken.
- Worst-case running time = height of tree.
Lower Bound for decision-tree Sorting
Theorem: Any comparison sorting algorithm requires Ω(n lgn) comparisons in the worst case
Corollary(推论): Heapsort and merge sort are asymptotically optimal comparison sorting algorithms.(堆排序和归并排序都是渐进最优的比较排序算法)。
Counting Sort(计数排序)
输入数组A,输出排序好的数组B,数组C提供临时的存储空间。
-
For x in A, if there are 17 elements less than x in A, then x belongs in output position 18.
-
How if several elements in A have the same value?
(Put the 1st in position 18, 2nd in position 19,3rd in position 20,…)即该排序算法是稳定的。 -
How if there are 17 elements not greater than x in A?
Put the last one in position 17, the penultimate one in position 16,…
数组内元素的取值范围为[0…k]
void COUNTING_SORT(int A[],int B[],int k)
{
int C[k];
for(int i=0;i<k;i++)
C[i]=0;
int length=5;
//记录A中每个取值为i的个数
for(int j=0;j<length;j++)
C[A[j]-1]=C[A[j]-1]+1;
//统计<=i的数有多少
for(int i=1;i<k;i++)
C[i]=C[i]+C[i-1];
for(int j=length-1;j>=0;j--)
{
B[C[A[j]-1]-1]=A[j];
C[A[j]-1]=C[A[j]-1]-1;
}
}
主函数验证:
int main()
{
int A[]={4,1,3,4,3};
int B[5];
int k=4;
COUNTING_SORT(A,B,k);
for(int i=0;i<5;i++)
cout<<B[i]<<" ";
}
初始化:
执行完第一步:
统计A中每种元素的个数:
统计结束:
记录每种元素之前及自身的个数(<=i);
统计结束:
根据C中的统计结果,将C的数组号传入B中,此时已经是排序好的:
j=5:
j=4:
j=3:
j=2:
j=1:
最终结果:
Analysis of Counting Sort
该算法非常适合k很小,n很大的情况,即数很小,但元素很多的情况。
Stable sorting
- Counting sort is a stable sort: it preserves the input order among equal elements.
Radix sort(基数排序)
- Origin: Herman Hollerith’s card-sorting machine for the 1890 U.S. Census.
- Digit-by-digit sort.
- Hollerith’s original (bad) idea: sort on most-significant digit first.
- Good idea: Sort on least-significant digit first with auxiliary(辅助) stable sort.
伪代码:
Bucket Sort(桶排序)
- Like counting sort, bucket sort is fast because it assumes something about the input. Whereas counting sort assumes that the input consists of integers in a small range, bucket sort assumes that the input is generated by a random process that distributes elements uniformly. (桶排序假设输入是由一个随机过程产生,该过程将元素均匀地独立地分布在[0,1)区间上。)
Summary of sorting algorithms