桶排序:假设输入·数据服从均匀分布,平均情况下他的时间代价为O(n).桶排序假设输入是一个随机过程,该过程元素都均匀独立分布在[0,1)区间。桶排序将区间[0,1)划分为n个大小相同的区间或称为桶,然后将n个数据分别放入桶中,我们先对每个桶进行排序,然后再遍历所有桶将结果串起来。
比如对double a[10] = { 0.79, 0.13, 0.16, 0.64, 0.39, 0.20, 0.89, 0.53, 0.71, 0.42 };数组进行排序,首先建立10个桶bucket,编号0,1,2...10,而数字a[i]应放在int j=10*a[i],的bucke[j]中。
bucket 数据
0 /
1 0.13->0.16->/
2 0.20->/
3 0.39->/
4 0.42->/
5 0.53->/
6 0.64->/
7 0.71->0.79->/
8 0.89->/
9 /
下面代码略有不同,在每个桶头结点设计了一个哨兵,并n=10进行测试。
#include<iostream>
using namespace std;
#define MIN_VALUE -0.01
class Node{
public:
double r;
Node*next;
};
typedef Node*PNode;
PNode Bucket_sort(double a[], int n);
void Show_node(PNode head);
int main(){
/*取n=10来测试*/
const int n = 10;
double a[n] = { 0.79, 0.13, 0.16, 0.64, 0.39, 0.20, 0.89, 0.53, 0.71, 0.42 };
PNode head = Bucket_sort(a, n);
Show_node(head);
return 0;
}
PNode Bucket_sort(double a[], int n){
int i,j;
PNode p = nullptr,p1=nullptr,p2=nullptr;
PNode *bucket = new PNode[n]; //建立n个桶,需要注意的是bucket数组是n个指针,并没有分派指向的空间
for (i = 0; i < n; i++){ //初始化,bucket[i]为哨兵节点
bucket[i] = new Node; //先分配指向的空间
bucket[i]->r = MIN_VALUE;
bucket[i]->next = nullptr;
}
for (i = 0; i < n; i++){ //将数据分装到桶中,并将每个节点插入到桶中正确位置
p = new Node;
p->r = a[i];
j = n*a[i]; //计算桶的位置下标
p1 = bucket[j];
p2 = p1->next;
while (p2&&a[i]>p2->r){ //链表的插入排序
p1 = p1->next;
p2 =p2->next;
}//p1是p的前驱节点,p2是p的后继节点
p1->next = p;
p->next = p2;
}
i = 0;
while (!bucket[i]->next) i++;
PNode head = bucket[i]->next; //头结点找到
p =head;
while (p->next) p = p->next; //向后寻找尾结点
PNode rear = p; //找到尾结点
for (i = i + 1; i < n; i++){
if (bucket[i]->next){
rear->next= bucket[i]->next; //串起来
p = rear->next;
while (p->next) p = p->next; //向后寻找尾结点
rear = p; //找到新的尾结点
}
}
rear->next = nullptr;
return head;
}
void Show_node(PNode head){
PNode p = head;
while (p){
cout << p->r << " ";
p = p->next;
}
cout << endl;
}