日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

count sort, radix sort, bucket sort

發布時間:2024/4/11 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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&lt;=nck &lt;= 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

#include <string> #include <algorithm> #include <vector> #include <iostream>using namespace std;void countSort(vector<int>& nums, int exp) {int sz = nums.size();vector<int> output(sz, 0);vector<int> count(10, 0);for (auto n : nums)count[(n/exp)%10]++;//count[i]表示i前面有count[i]個數字。i處填nums[count[i]]for (int i = 1; i < 10; i++)count[i] += count[i-1];//從后面開始放nums,穩定的排序for (int i = sz-1; i >= 0; i--){output[count[(nums[i]/exp)%10]-1] = nums[i];count[(nums[i]/exp)%10]--;}nums = output; }void radix_sort(vector<int>& nums) {int m = *max_element(nums.begin(), nums.end());for (int exp = 1; m/exp > 0; exp *= 10)countSort(nums, exp); }int main() {int arr[] = {170, 45, 75, 90, 802, 24, 2, 66};vector<int> test(arr, arr+sizeof(arr)/sizeof(int));radix_sort(test);for (auto r : test)cout << r << " ";cout << endl;}

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], &#x27;b&#x27;1bba[1]b\rightarrow2baa放到[2],′b′2 baa放到[2], &#x27;b&#x27;2baa[2]b\rightarrow$2

0……‘a’‘b’‘c’
0……132

……然后以這種方法分別對第2個,第3個字符排序。

下面用msd的方法對一個字符串數組進行按字典序排列。

  • 根據首字母將數組分成R部分,使用counting sort。
  • 遞歸地對這R部分使用counting sort。(為了使待排序的字符串的長度不固定,可以統計字符串結束時候的’\0’,并且遞歸地時候,直接略過該字符串。)
  • #include <vector> #include <iostream> #include <string>using namespace std;//lo~hi表示待排序的字符串為sVec[lo, hi-1]。 void msd(vector<string>& sVec, int lo, int hi, int pos) {const int N = 256+1;if (hi <= lo+1) return;vector<int> count(N, 0);vector<string> temp(hi-lo, "");int sz = sVec.size();//這和一般的count sort計法略有不同。整體往后移了一位for (int i = lo; i < hi; i++)count[sVec[i][pos]+1]++;for (int i = 1; i < N; i++)count[i] += count[i-1];//這里雖然是從前往后放置,但是仍然是穩定的。因為前面的計數的時候,計的是count[sVec[i][pos]+1],但是旋轉的時候,是從count[sVec[i][pos]]開始放的。for (int i = lo; i < hi; i++){temp[count[sVec[i][pos]]] = sVec[i];count[sVec[i][pos]]++; //相當于把count數組往前移了一個元素}for (int i = lo; i < hi; i++)sVec[i] = temp[i-lo];for (int i = 1; i < N-1; i++)msd(sVec, lo+count[i], lo+count[i+1], pos+1); //count[i]~count[i+1]相當于對索引為i的元素排序。 }void msd(vector<string>& sVec) {msd(sVec, 0, sVec.size(), 0); }int main() {string s[] = {"dabggg","adda","cabeu","fab","fee","bad","dad","bee","fed","bed","ebb","ace"};vector<string> test(s, s+sizeof(s)/sizeof(string));msd(test);for (auto r : test)cout << r << endl; }

    桶排序

    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的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。