count sort, radix sort, bucket sort
count sort, radix sort, bucket sort
標簽(空格分隔): algorithms
基于比較的排序算法,都逃不過O(nlogn)O(nlogn)O(nlogn)的宿命1。而非基于比較的排序,如計數排序,基數排序,桶排序則無此限制。它們充分利用待排序的數據的某些限定性假設,來避免絕大多數的“比較”操作。
計數排序
http://www.geeksforgeeks.org/counting-sort/
時間復雜度:O(N+K)O(N+K)O(N+K),N為元素個數,K為元素最大值。是一種穩定的排序算法。
但是我覺得時間復雜度其實還是O(N)O(N)O(N),因為不管是計數還是最后把每個元素放入正確的位置都是O(N)O(N)O(N)。
#include <string> #include <vector> #include <iostream>using namespace std;/* O(n+k) 最后count數組相當于往后移了一個元素。 */void count_sort(string &s) {const int range = 255;vector<int> count(range+1,0);for (auto c : s)count[c]++;for (int i = 1; i <= range; i++)count[i] += count[i-1];string temp(s.size(), ' ');//如果改成從右到左循環,則是穩定的。//當然還有一種做法,即不用累加count數組,直接掃描count數組,設置一個全局index,這樣會有問題:不穩定。但改成從右到左循環,還是穩定的。/*for (int i = s.size()-1; i >= 0; i--){temp[count[s[i]] = s[i];count[s[i]]--;}*/for (auto c : s){temp[count[c]-1] = c;count[c]--;}s = temp;}int main() {string s = "geeksforgeeks";count_sort(s);cout << s << endl; }基數排序
http://www.geeksforgeeks.org/radix-sort/
http://notepad.yehyeh.net/Content/Algorithm/Sort/Radix/Radix.php
基數排序的底層排序可以用計數排序或者桶排序。
Let there be ddd digits in input integers. Radix Sort takes O(d?(n+b))O(d*(n+b))O(d?(n+b)) time where bbb is the base for representing numbers, for example, for decimal system, bbb is 10. What is the value of ddd? If kkk is the maximum possible value, then ddd would be O(logb(k))O(log_b(k))O(logb?(k)). (比如k=1000,b=10,則d=3)So overall time complexity is O((n+b)?logb(k))O((n+b) * log_b(k))O((n+b)?logb?(k)). Which looks more than the time complexity of comparison based sorting algorithms for a large kkk. Let us first limit kkk. Let k<=nck <= n^ck<=nc where ccc is a constant. In that case, the complexity becomes O(nlogb(n))O(nlog_b(n))O(nlogb?(n)). But it still doesn’t beat comparison based sorting algorithms.
What if we make value of bbb larger?. What should be the value of bbb
to make the time complexity linear? If we set bbb as nnn, we get the
time complexity as O(n)O(n)O(n). In other words, we can sort an array of
integers with range from 1 to ncn^cnc if the numbers are represented in
base nnn (or every digit takes log2(n)log_2(n)log2?(n) bits).
上面最后一段說,如果要給111~ncn^cnc之內的以nnn為基數的數組排序,那么就可以用線性的復雜度完成。
問題:對[0,n2?1][0,n^2-1][0,n2?1]的nnn 個整數進行線性時間排序。
方法1是先把整數轉換成n進制再排序,這樣每個數有兩位,范圍為[0…n-1],再進行基數排序。http://blog.csdn.net/mishifangxiangdefeng/article/details/7685839
LSD:從關鍵字優先級低的開始排,循環
MSD:從關鍵字優先級高的開始排,遞歸
lsd適合于定長的字符串數組排序:
void lsd(vector<string>& sVec) {const int N = 256+1;int w = sVec[0].length();int sz = sVec.size();for (int d = w-1; d >= 0; d--){vector<int> count(N, 0);vector<string> temp(N, "");for (int i = 0; i < sz; i++)count[sVec[i][d]+1]++;for (int i = 1; i < N; i++)count[i] += count[i-1];for (int i = 0; i < sz; i++){temp[count[sVec[i][d]]] = sVec[i];count[sVec[i][d]]++;}for (int i = 0; i < sz; i++)sVec[i] = temp[i]; } }int main() {//lsdstring s1[] = {"dab","add","cab","fab","fee","bad","dad","bee","fed","bed","ebb","ace"};vector<string> test1(s1, s1+sizeof(s1)/sizeof(string));msd(test1);for (auto r : test1)cout << r << endl; }下面是程序中的count計數方法:
vector sVec: aab, bba, baa。
計的是count[sVec[i][d]+1]++;所以計數如下:
| 0 | …… | ‘a’ | ‘b’ | ‘c’ |
|:----?:----?:----?:----?
| 0 | …… | 0 | 1 | 2 |
第一輪排序(即按第一個字符排序)按count數組將string放置到正確的位置:
aab放到[0],‘a’$\rightarrow1bba放到[1],′b′1 bba放到[1], 'b'1bba放到[1],′b′\rightarrow2baa放到[2],′b′2 baa放到[2], 'b'2baa放到[2],′b′\rightarrow$2
| 0 | …… | 1 | 3 | 2 |
……然后以這種方法分別對第2個,第3個字符排序。
下面用msd的方法對一個字符串數組進行按字典序排列。
桶排序
http://www.geeksforgeeks.org/bucket-sort-2/
#include <vector> #include <iostream> #include <algorithm>using namespace std;void bucket_sort(vector<double>& nums) {vector<vector<double>> bucket(10, vector<double>(0));for (auto num : nums)bucket[10*num].push_back(num);for (int i = 0; i < 10; i++)sort(bucket[i].begin(), bucket[i].end());int index = 0;//10個桶for (int i = 0; i < 10; i++){for (int j = 0; j < bucket[i].size(); j++) nums[index++] = bucket[i][j];} }int main() {double arr[] = {0.897, 0.565, 0.656, 0.1234, 0.665, 0.3434};vector<double> test(arr, arr+sizeof(arr)/sizeof(double));bucket_sort(test);for (auto r : test)cout << r << " ";cout << endl; }對該算法簡單分析,如果數據是期望平均分布的,則每個桶中的元素平均個數為N/M。如果對每個桶中的元素排序使用的算法是快速排序,每次排序的時間復雜度為O(N/Mlog(N/M))。則總的時間復雜度為O(N)+O(M)O(N/Mlog(N/M)) = O(N+ Nlog(N/M)) = O(N + NlogN - NlogM)。當M接近于N是,桶排序的時間復雜度就可以近似認為是O(N)的。就是桶越多,時間效率就越高,而桶越多,空間卻就越大,由此可見時間和空間是一個矛盾的兩個方面1。
1:https://www.byvoid.com/blog/sort-radix
平均復雜度為O(n)O(n)O(n):將元素放入桶中O(n)O(n)O(n),收集元素O(n)O(n)O(n),sort平均O(n)O(n)O(n)。
#reference
http://segmentfault.com/a/1190000003054515#articleHeader2
http://hxraid.iteye.com/blog/647759(桶排序效率分析)
https://www.cs.princeton.edu/~rs/AlgsDS07/18RadixSort.pdf(princeton radix sort)
http://segmentfault.com/a/1190000002595152 ?? ?? ?? ??
總結
以上是生活随笔為你收集整理的count sort, radix sort, bucket sort的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Union-find
- 下一篇: 【原创】“三次握手,四次挥手”你真的懂吗