浅显易懂的桶排序
想准备将所有的排序算法都总结出来,方便你查阅,也方便我复习和记忆,下面来说桶排序:
首先必须申明,桶排序和计数排序完全不同,不可混为一谈:(这里实例用单链表来操作)
还是老方法,看文字就是烦,直接上图,图文结合,永远都是王道:
1.假设:桶待排序列:{ 49, 38, 35, 97, 76, 73, 27, 49 ,34,78}
看了之后有没有特莫感觉就是哈希桶,哈哈,满足一定条件差不多就是啦;言归正传,key值就是待排序序列,Bucket为桶,数据按某种函数,映射到桶中
2.关于映射及桶排原理分析:
桶中数据的十位都一样,那么映射函数算出的桶号就是这些数据的十位,也就是说,这种映射函数,目的就是为了找出数据的共同特点,可能是求余(哈希表直接定址,就是这样),可能是除某数求商,本例中就是取商;
即就是所有数据除某数取得的商相同的都放一个桶中,如图中的3号桶,刚开始,3号桶中的数据是无序的,第一遍操作,只能保证这些数据一定是在这个桶中,
但是桶中的顺序还是要排的,之后,遍历一遍桶,输出即就是一个有序序列,就这几句话,我感觉说完了,至于更深层 的剖析,稍后再说,先来代码:
#pragma once //每一个节点的结构 struct node { int key; //关键字,在桶中统计桶中数据量,在数据节点中就是节点的数据 struct node *next; }; //声明: void PrintBucketSort(node** bucket, int bucket_size); int f(int x); void BucketSort(int* a, int size,int bucket_size) { assert(a); //给桶申请空间 node** bucket = new node*[bucket_size*sizeof(node)]; //初始化 for (int i = 0; i < bucket_size; ++i) { bucket[i] = new node[sizeof(node)]; //每一个桶 bucket[i]->key = 0; bucket[i]->next = nullptr; } for (int j = 0; j < size; ++j) { node* sub_node = new node[sizeof(node)]; //桶下的每一个节点 sub_node->key = a[j]; sub_node->next = nullptr; //计算这数据在哪个桶中 int num = f(a[j]); //让一个指针指向这个桶号的头 node* sub_head = bucket[num]; //开始插入 if (sub_head->next == nullptr) { bucket[num]->next = sub_node; bucket[num]->key++; } //该桶号不为空,那么插入排序 else { while (sub_head->next != nullptr && sub_node->key >= sub_head->next->key) { sub_head = sub_head->next; } sub_node->next = sub_head->next; sub_head->next = sub_node; bucket[num]->key++; } } //打印 PrintBucketSort(bucket, bucket_size); } //映射函数 int f(int x) { return (x / 10); } //打印 void PrintBucketSort(node** bucket, int bucket_size) { //多少桶链(桶号) for (int i = 0; i < bucket_size; ++i) { node* cur = bucket[i]->next; while (cur) { cout << cur->key << " "; cur = cur->next; } } cout << endl; } void Test7() { int a[10] = { 49, 38, 35, 97, 76, 73, 27, 49, 34, 78 }; cout << "桶排序" << endl; BucketSort(a, 10, 10); //桶数据最大才97,所以需要10个桶 }哎呀,敲了我十几分钟,看看结果:
第一个就是排序,第二个就是数据在桶中的分布,横行代表桶,10个桶,没有数据的桶是0;
桶排序就是这样:
对于N个待排数据,M个桶,平均每个桶[N/M]个数据的桶排序平均时间复杂度为:
O(N)+O(M*(N/M)*log(N/M))=O(N+N*(logN-logM))=O(N+N*logN-N*logM)
当N=M时,即极限情况下每个桶只有一个数据时。桶排序的最好效率能够达到O(N)。
桶排序的平均时间复杂度为线性的O(N+C),其中C=N*(logN-logM)。如果相对于同样的N,桶数量M越大,其效率越高,最好的时间复杂度达到O(N)。
当然桶排序的空间复杂度 为O(N+M),如果输入数据非常庞大,而桶的数量也非常多,则空间代价无疑是昂贵的。
此外,桶排序是稳定的。
赐教!