经典排序算法(9)——桶排序算法详解
桶排序(Bucket sort)或所謂的箱排序,并不是比較排序,它不受到 O(nlogn) 下限的影響。
一、算法基本思想
(1)基本思想
桶排序工作的原理是將數(shù)組分到有限數(shù)量的桶子里,每個(gè)桶子再個(gè)別排序,有可能再使用別的排序算法或是以遞歸方式繼續(xù)使用桶排序進(jìn)行排序。桶排序是鴿巢排序的一種歸納結(jié)果。當(dāng)要被排序的數(shù)組內(nèi)的數(shù)值是均勻分配的時(shí)候,桶排序使用線性時(shí)間O(n)。
(2)運(yùn)行過程
桶排序算法的運(yùn)行過程如下:
1、設(shè)置一個(gè)定量的數(shù)組當(dāng)作空桶子。
2、尋訪序列,并且把項(xiàng)目一個(gè)一個(gè)放到對(duì)應(yīng)的桶子去。
3、對(duì)每個(gè)不是空的桶子進(jìn)行排序。
4、從不是空的桶子里把項(xiàng)目再放回原來的序列中。
(3)示例
二、算法實(shí)現(xiàn)(核心代碼)
C++實(shí)現(xiàn):假設(shè)數(shù)據(jù)分布在[0,100)之間,每個(gè)桶內(nèi)部用鏈表表示,在數(shù)據(jù)入桶的同時(shí)插入排序。然后把各個(gè)桶中的數(shù)據(jù)合并。
#include<iterator> #include<iostream> #include<vector> using namespace std; const int BUCKET_NUM = 10;struct ListNode{explicit ListNode(int i=0):mData(i),mNext(NULL){}ListNode* mNext;int mData; };ListNode* insert(ListNode* head,int val){ListNode dummyNode;ListNode *newNode = new ListNode(val);ListNode *pre,*curr;dummyNode.mNext = head;pre = &dummyNode;curr = head;while(NULL!=curr && curr->mData<=val){pre = curr;curr = curr->mNext;}newNode->mNext = curr;pre->mNext = newNode;return dummyNode.mNext; }ListNode* Merge(ListNode *head1,ListNode *head2){ListNode dummyNode;ListNode *dummy = &dummyNode;while(NULL!=head1 && NULL!=head2){if(head1->mData <= head2->mData){dummy->mNext = head1;head1 = head1->mNext;}else{dummy->mNext = head2;head2 = head2->mNext;}dummy = dummy->mNext;}if(NULL!=head1) dummy->mNext = head1;if(NULL!=head2) dummy->mNext = head2;return dummyNode.mNext; }void BucketSort(int n,int arr[]){vector<ListNode*> buckets(BUCKET_NUM,(ListNode*)(0));for(int i=0;i<n;++i){int index = arr[i]/BUCKET_NUM;ListNode *head = buckets.at(index);buckets.at(index) = insert(head,arr[i]);}ListNode *head = buckets.at(0);for(int i=1;i<BUCKET_NUM;++i){head = Merge(head,buckets.at(i));}for(int i=0;i<n;++i){arr[i] = head->mData;head = head->mNext;} }
三、性能(算法時(shí)間、空間復(fù)雜度、穩(wěn)定性)分析
假設(shè)有n個(gè)數(shù)字,有m個(gè)桶,如果數(shù)字是平均分布的,則每個(gè)桶里面平均有n/m個(gè)數(shù)字。如果 對(duì)每個(gè)桶中的數(shù)字采用快速排序,那么整個(gè)算法的復(fù)雜度是 O(n + m * (n/m) * log(n/m)) =O(n + nlogn – nlogm) 。
從上式看出,當(dāng)m接近n的時(shí)候,桶排序時(shí)間復(fù)雜度接近O(n)。當(dāng)然,以上復(fù)雜度的計(jì)算是基于輸入的n個(gè)數(shù)字是平均分布這個(gè)假設(shè)的。這個(gè)假設(shè)是很強(qiáng)的 ,實(shí)際應(yīng)用中效果并沒有這么好。
如果所有的數(shù)字都落在同一個(gè)桶中,那就退化成一般的排序了。 前面說的幾大排序算法 ,大部分時(shí)間復(fù)雜度都是O(n^2),也有部分排序算法時(shí)間復(fù)雜度是O(nlogn)。而桶式排序卻能實(shí)現(xiàn)O(n)的時(shí)間復(fù)雜度。
但桶排序的缺點(diǎn)是: 1)首先是空間復(fù)雜度比較高,需要的額外開銷大。排序有兩個(gè)數(shù)組的空間開銷,一個(gè)存放待排序數(shù)組,一個(gè)就是所謂的桶,比如待排序值是從0到m-1,那就需要m個(gè)桶,這個(gè)桶數(shù)組就要至少m個(gè)空間。 2)其次待排序的元素都要在一定的范圍內(nèi)等等。
通排序的空間復(fù)雜度為O(n+m)。
桶排序的穩(wěn)定性依賴于桶內(nèi)排序。如果我們使用了快排,顯然,算法是不穩(wěn)定的。
總結(jié)
以上是生活随笔為你收集整理的经典排序算法(9)——桶排序算法详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 经典排序算法(8)——归并排序算法详解
- 下一篇: 华为联合设计,AITO 问界新 M7 车