Introduction to Algorithm(chapter 8)
2012-11-16 08:48
411 查看
基于比较的排序都有一个下界w(n*lgn),因为基于比较的排序都可以通过建立一颗决策树来表示,其中叶子节点代表最终的排序结果,这颗树共有n!个叶子,那其中从根到叶子的最长路径就代表了最坏情况下的比较次数,即树的高度h。对于一颗h高的树,叶子节点不多2^h,而这颗决策树的叶子个数为n!故,n!<=2^h..-> h>=lg(n!) = w(n*lgn),故基于比较的排序都有此下界。
而计数排序则不是基于比较的排序,它利用了元素的大小特点并采用一定的辅助空间来完成排序,假设一组数A
(序号0...n-1),其中每一个元素大小在0...k之间,那么就可以利用一个辅助数组C[k+1](序号0...k)来完成排序,先初始化C[i]=0,然后遍历A[i],统计每个A[i]出现的次数即C[A[i]]++,这步操作后C[i]就代表i一共出现了多少次,然后遍历C并
C[i] = C[i]+C[i-1],这步操作后C[i]就代表了小于等于i的元素共出现了多少次,例如假设A[i] = 5,C[A[i]]= 3,那么就代表小于等于5的元素出现了三个,那么我们就应该将5放在第三个位置上即B[C[A[i]]-1] = A[i](注意第三个位置对应于C语言中的B[2]故C[A[i]]-1对应于C语言中的下标),因为可能存在不止一个5,所以放置过5后,我们要减少小于等于5出现的次数即C[A[i]]--,这样如果还有5出现的话那么它应该放置在第二个位置上。
算法:
// a array of n elements whose element is between 0---k
void countSort(int A[],int B[],int n,int k)
{
int* C = new int[k+1];//对应于0...k
for(int i=0;i<=k;i++)
C[i] =0;
for(int i=0;i<n;i++)
C[A[i]]++;//C[i]:i出现的次数
for(int i=1;i<=k;i++)
C[i] = C[i]+C[i-1];//C[i]:小于等于i的个数
print(C,k+1);
//注意这里采用的是从后往前遍历,这样就保证了算法的稳定性,假如初始A中有两个相同的数...6....6,而且C[6] = //10,那么从后往前遍历时遇到第一个6时将6放置在10位置处同时C[6]-- = 9,往前遍历遇到第二个6时那么这个6就放 //置在9位置处,这样就保证了计数排序是稳定的。
for(int j =n-1;j>=0;j--)
{
B[C[A[j]]-1] = A[j];//将每个A[j]放在和自己排名对应的地方
C[A[j]]--;//可能出现多个A[j],故减1以使下一次出现时将它放在前一个位置上而不重叠
}
delete []C;
}
计数排序思想有点类似于考试排名,给每个学生一个排名,那么对结果排序时就应该将该学生信息放到和排名对应的栏目中,如果出现考试排名相同的情况那么即将相同的放到前一个位置,不同点即是计数排序利用了元素本身大小的信息而考试排名没用到,但将信息放到和排名对应的位置这点思想还是相似的。
习题8后面有个水壶配对的思考题,这个问题的答案很精彩,利用了快排的的思想,值得关注。
而计数排序则不是基于比较的排序,它利用了元素的大小特点并采用一定的辅助空间来完成排序,假设一组数A
(序号0...n-1),其中每一个元素大小在0...k之间,那么就可以利用一个辅助数组C[k+1](序号0...k)来完成排序,先初始化C[i]=0,然后遍历A[i],统计每个A[i]出现的次数即C[A[i]]++,这步操作后C[i]就代表i一共出现了多少次,然后遍历C并
C[i] = C[i]+C[i-1],这步操作后C[i]就代表了小于等于i的元素共出现了多少次,例如假设A[i] = 5,C[A[i]]= 3,那么就代表小于等于5的元素出现了三个,那么我们就应该将5放在第三个位置上即B[C[A[i]]-1] = A[i](注意第三个位置对应于C语言中的B[2]故C[A[i]]-1对应于C语言中的下标),因为可能存在不止一个5,所以放置过5后,我们要减少小于等于5出现的次数即C[A[i]]--,这样如果还有5出现的话那么它应该放置在第二个位置上。
算法:
// a array of n elements whose element is between 0---k
void countSort(int A[],int B[],int n,int k)
{
int* C = new int[k+1];//对应于0...k
for(int i=0;i<=k;i++)
C[i] =0;
for(int i=0;i<n;i++)
C[A[i]]++;//C[i]:i出现的次数
for(int i=1;i<=k;i++)
C[i] = C[i]+C[i-1];//C[i]:小于等于i的个数
print(C,k+1);
//注意这里采用的是从后往前遍历,这样就保证了算法的稳定性,假如初始A中有两个相同的数...6....6,而且C[6] = //10,那么从后往前遍历时遇到第一个6时将6放置在10位置处同时C[6]-- = 9,往前遍历遇到第二个6时那么这个6就放 //置在9位置处,这样就保证了计数排序是稳定的。
for(int j =n-1;j>=0;j--)
{
B[C[A[j]]-1] = A[j];//将每个A[j]放在和自己排名对应的地方
C[A[j]]--;//可能出现多个A[j],故减1以使下一次出现时将它放在前一个位置上而不重叠
}
delete []C;
}
计数排序思想有点类似于考试排名,给每个学生一个排名,那么对结果排序时就应该将该学生信息放到和排名对应的栏目中,如果出现考试排名相同的情况那么即将相同的放到前一个位置,不同点即是计数排序利用了元素本身大小的信息而考试排名没用到,但将信息放到和排名对应的位置这点思想还是相似的。
习题8后面有个水壶配对的思考题,这个问题的答案很精彩,利用了快排的的思想,值得关注。
相关文章推荐
- Introduction to Algorithm(chapter 6)
- Introduction to algorithm(chapter 13)
- Introduction to Algorithm - Summary of Chapter 2(2) - Merge Sort
- Introduction to Algorithm( chapter 9 and 10)
- Introduction to Algorithm(chapter 3 and 4)
- Introduction to Algorithm(chapter 14)
- Introduction to Algorithm - Summary of Chapter 1 - The Role of Algorithm in Computing
- Introduction to Algorithm(chapter 7)
- Medians and Order Statistics - Introduction to Algorithm - Summary of Chapter 9
- Introduction to Algorithm(chapter 11)
- Growth of Functions - Introduction to Algorithm - Summary of Chapter 3
- Introduction to Algorithm - Summary of Chapter 7 - Quicksort
- Introduction to Algorithm - Summary of Chapter 2(1) - Insertion sort
- Introduction to Algorithm(chapter 5)
- Introduction to Algorithm(chapter 12)
- Introduction to Algorithm - Summary of Chapter 8 - Sorting in Linear Time
- Introduction to Algorithm - Summary of Chapter 6 - Heapsort
- Introduction to Algorithm - Summary of Chapter 2(0) - Getting started
- Introduction to Algorithm ( chapter 15: Dynamic Programming)
- 算法导论第八章习题答案(第三版) Introduction to Algorithm