三种线性排序算法 计数排序、桶排序与基数排序
/* Problem: Counting Sort
* Author: Guo Jiabao
* Time: 2009.3.29 16:27
* State: Solved
* Memo: 计数排序
*/
#include
#include
#include
#include
#include
using namespace std;
void CountingSort(int *A,int *B,int *Order,int N,int K) {
int *C=new int[K+1];
int i;
memset(C,0,sizeof(int)*(K+1));
}
for (i=1;i<=N;i++)
//把A中的每个元素分配
C[A[i]]++;
for (i=2;i<=K;i++)
//统计不大于i的元素的个数
C[i]+=C[i-1];
for (i=N;i>=1;i--){
B[C[A[i]]]=A[i];
//按照统计的位置,将值输出到B中,将顺序输出到Order中
Order[C[A[i]]]=i;
C[A[i]]--;
}
}
int main() {
int *A,*B,*Order, N=15, K=10, i;
A=new int[N+1];
B=new int[N+1];
Order=new int[N+1];
for (i=1; i<=N; i++){
A[i]=rand()%K + 1;
}
//生成1..K的随机数
printf("Before CS:\n");
for (i=1;i<=N;i++){
printf("%d ",A[i]);
}
CountingSort(A, B, Order, N, K);
printf("\nAfter CS:\n");
for (i=1;i<=N;i++){
printf("%d ",B[i]);
}
printf("\nOrder:\n");
for (i=1;i<=N;i++){
printf("%d ",Order[i]);
}
return 0;
}
}
/**
* * Problem: Bucket Sort
* Author: Guo Jiabao
* Time: 2009.3.29 16:32
* State: Solved
* Memo: 桶排序特殊实现
* */
#include
#include #include
#include #include
using namespace std;
void BucketSort(int *A,int *B,int N,int K) {
int *C=new int[K+1]; int i,j,k;
memset(C,0,sizeof(int)*(K+1));
for (i=1;i<=N;i++) //把A中的每个元素按照值放入桶中
C[A[i]]++;
for (i=j=1;i<=K;i++,j=k){ //统计每个桶元素的个数,并输出到B
for (k=j;k
/*
* * Problem: Bucket Sort
* * Author: Guo Jiabao
* * Time: 2009.3.29 16:50
* * State: Solved
* * Memo: 桶排序一般实现
* */
#include
#include
#include
#include
#include
using namespace std;
struct linklist {
linklist *next;
int value;
linklist(int v,linklist *n):
value(v),next(n){
}
~linklist() {
if (next)
delete next;
}
};
inline int cmp(const void *a,const void *b) {
return *(int *)a-*(int *)b;
}
/* 为了方便,我把A中元素加入桶中时是倒序放入的,而收集取出时也是倒序放入序列的,所以不违背稳定排序。 */
void BucketSort(int *A,int *B,int N,int K) {
linklist *Bucket[101],*p;//建立桶 int i,j,k,M;
M=K/100;
memset(Bucket,0,sizeof(Bucket));
for (i=1;i<=N;i++) { k=A[i]/M;
//把A中的每个元素按照的范围值放入对应桶中
Bucket[k]=new linklist(A[i],Bucket[k]);
}
for (k=j=0;k<=100;k++) {
i=j;
for (p=Bucket[k];p;p=p->next)
B[++j]=p->value;
//把桶中每个元素取出,排序并加入B
delete Bucket[k];
qsort(B+i+1,j-i,sizeof(B[0]),cmp);
}
}
int main() {
int *A,*B,N=100,K=10000,i;
A=new int[N+1];
B=new int[N+1];
for (i=1;i<=N;i++) A[i]=rand()%K+1;
//生成1..K的随机数
BucketSort(A,B,N,K);
for (i=1;i<=N;i++) {
printf("%d ",B[i]);
}
return 0;
}
}
}
/* * Problem: Radix Sort
* * Author: Guo Jiabao
* * Time: 2009.3.29 16:50
* * State: Solved
* * Memo: 基数排序 结构数组
* */
#include
#include
#include
#include
#include
using namespace std;
struct data {
int key[2];
};
struct linklist {
linklist *next;
data value;
linklist(data v,linklist *n):
value(v),next(n){}
~linklist() {
if (next)
delete next;
}
};
void BucketSort(data *A,int N,int K,int y) {
linklist *Bucket[101],*p;
//建立桶 int i,j,k,M;
M=K/100+1;
memset(Bucket,0,sizeof(Bucket));
for (i=1;i<=N;i++) { k=A[i].key[y]/M;
//把A中的每个元素按照的范围值放入对应桶中
Bucket[k]=new linklist(A[i],Bucket[k]);
}
for (k=j=0;k<=100;k++) {
for (p=Bucket[k];p;p=p->next)
j++;
for (p=Bucket[k],i=1;p;p=p->next,i++)
A[j-i+1]=p->value;
//把桶中每个元素取出 delete Bucket[k]; }
} void RadixSort(data *A,int N,int K) {
for (int j=1;j>=0;j--) //从低优先到高优先 LSD
BucketSort(A,N,K,j);
}
int main() {
int N=100,K=1000,i;
data *A=new data[N+1];
for (i=1;i<=N;i++) {
A[i].key[0]=rand()%K+1;
A[i].key[1]=rand()%K+1;
}
RadixSort(A,N,K);
for (i=1;i<=N;i++)
printf("(%d,%d) ",A[i].key[0],A[i].key[1]);
printf("\n");
return 0; }
}
}
在实际应用中,基数排序可以用于后缀数组的倍增算法,使时间复杂度从O(NlogNlogN)降到O(N*logN)。线性排序算法使用最重要的是,充分利用数据特殊的性质,以达到最佳效果。