介绍两种非基于比较的排序算法。前面提到的排序算法,快排,堆排,合并等都是通过比较元素之间的大小来进行排序的,基于比较的排序是不能突破
NLog2N
的下界的。而这两种算法的时间复杂度是可以达到
O(N)
的,当然它收到一定条件的限制。
计数排序:
计数排序假设输入数据的范围已经知道,并且是在一个确定的范围内,如
(0,K]
内。基本思路是:对于每一个输入数据X,确定小于X的元素个数,利用这个特性,就可以确定X在输出数组中的位置。例如:
X=18
,数组中小于X的元素个数为7,则X就应该在输出数组中的第8个位置上,如果出现相同的元素时稍微做一下变形就可以。
下面我给出一个简单的实现:
/*
Problem:Counting Sort
State:Sloved
Author:Liang Shaocong
Date:2015/4/5
*/
#include <iostream>
#include <ctime>
#include <cstring>
#include <vector>
const int LENGTH=20;
const int MAX_NUM=100;
int Order[LENGTH+1];
void Counting_Sort(int A[],int B[],int C[]){
for(int i=0;i<=MAX_NUM;i++)
C[i]=0;
//统计每个位置的元素个数
for(int i=1;i<=LENGTH;i++)
C[A[i]]=C[A[i]]+1;
//确定位置
for(int i=1;i<=MAX_NUM;i++)
C[i]=C[i]+C[i-1];
//确定输出位置
for(int j=LENGTH;j>=1;j--){
B[C[A[j]]]=A[j];
Order[C[A[j]]]=j;
C[A[j]]=C[A[j]]-1;
}
for(int j=1;j<=LENGTH;j++)
A[j]=B[j];
}
int main(void){
int A[LENGTH+1],B[LENGTH+1],C[MAX_NUM+1];
std::cout<<"Before Counting Sort:"<<std::endl;
//Initialize
for(int i=1;i<=LENGTH;i++){
A[i]=rand()%100+1;
std::cout<<A[i]<<" ";
}
std::cout<<std::endl;
Counting_Sort(A,B,C);
std::cout<<"After Counting Sort:"<<std::endl;
for(int i=1;i<=LENGTH;i++)
std::cout<<A[i]<<" ";
std::cout<<std::endl;
//在原来序列中的位置
std::cout<<"Location in primary array: "<<std::endl;
for(int i=1;i<=LENGTH;i++)
std::cout<<Order[i]<<" ";
}
桶排序:
桶排序也假设输入数据的范围确定,假设为
[0,100)
。这样便可以建立10个桶,其中每个桶分别存储
[0,10)
,
[10,20)
,
[20,30)
…….
[90,99)
之间的元素。把每一个输入数据放到相应的桶里,同时对每一个桶内部进行排序。最后再把桶合并。
下面是简单的实现:
/*
Problem:Bucket_Sort
Author:Liang Shaocong
Date:2015/4/9
State:Sloved
*/
#include <iostream>
#include <vector>
#include <ctime>
using std::cin;using std::cout;using std::endl;using std::vector;
const int BUCKET_NUM=10; //bucket number
const int N=20; //element number
struct Node{
int value;
Node *next;
explicit Node(int i=-1):value(i),next(nullptr){}
};
Node* Insert_Bucket(int value,Node* Bucket){
Node ivec;
Node *newNode=new Node(value);
Node *previous=&ivec,*current=Bucket;
ivec.next=Bucket;
while(current!=nullptr && current->value<=value){
previous=current;
current=current->next;
}
newNode->next=current;
previous->next=newNode;
return ivec.next;
}
Node* Merge_Bucket(Node *Bucket1,Node *Bucket2){
Node ivec;
Node *head=&ivec;
while(nullptr!=Bucket1 && nullptr!=Bucket2){
if(Bucket1->value<=Bucket2->value){
head->next=Bucket1;
Bucket1=Bucket1->next;
}else{
head->next=Bucket2;
Bucket2=Bucket2->next;
}
head=head->next;
}
if(nullptr!=Bucket1)
head->next=Bucket1;
if(nullptr!=Bucket2)
head->next=Bucket2;
return ivec.next;
}
void Bucket_Sort(int arr[],int n){
vector<Node*> Bucket(BUCKET_NUM,(Node*)(0));
//Insert to Bucket
for(int i=0;i<n;i++){
int index=arr[i]/BUCKET_NUM;
Node *head=Bucket.at(index);
Bucket.at(index)=Insert_Bucket(arr[i],head);
}
//header of the bucket
Node *head=Bucket.at(0);
//Merge these buckets
for(int i=1;i<BUCKET_NUM;i++)
head=Merge_Bucket(head,Bucket.at(i));
for(int i=0;i<n;i++){
arr[i]=head->value;
head=head->next;
}
}
int main(void){
int arr[N];
for(int i=0;i<N;i++)
arr[i]=rand()%100;
cout<<"Before Bucket Sort:"<<endl;
for(int i=0;i<N;i++)
cout<<arr[i]<<" ";
cout<<endl;
//Sort
Bucket_Sort(arr,N);
cout<<"After Sort: "<<endl;
for(int i=0;i<N;i++)
cout<<arr[i]<<" ";
return 0;
}
以上:
参考资料:
http://zh.wikipedia.org/wiki/%E6%A1%B6%E6%8E%92%E5%BA%8F
https://www.byvoid.com/blog/sort-radix