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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

七、排序(3)——线性排序

發布時間:2025/3/19 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 七、排序(3)——线性排序 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

時間復雜度是 O(n) 的排序算法:桶排序、計數排序、基數排序,也稱線性排序,他們都不是基于比較的排序算法。

一、桶排序

1、基本思想

將要排序的數據分到幾個有序的桶里,每個桶里的數據再單獨進行進行排序。桶內排完序之后,再把每個桶里的數據按照順序依次取出,從而形成有序序列。

2、桶排序對要排序數據的要求非常苛刻

  • 要排序的數據需要很容易就能劃分成 m 個桶,并且,桶與桶之間有著天然的大小順序。 ==》每個桶內的數據都排序完之后,桶與桶之間的數據不需要再進行排序。
  • 數據在各個桶之間的分布是比較均勻的。==》若數據不均勻 ==》時間復雜度就將退化為 O(nlogn) 的排序算法。

3、應用

適用于 外部排序。外部排序:數據存儲在外部磁盤中,數據量比較大,內存有限,無法將數據全部加載到內存中。

示例:有 10GB 的訂單數據,我們希望按訂單金額(假設金額都是正整數)進行排序,但是我們的內存有限,只有幾百 MB,沒辦法一次性把 10GB 的數據都加載到內存中。這個時候該怎么辦呢?

思路:

  • 先掃描一遍文件,看訂單金額所處的數據范圍。==》1元 ~ 10萬元
  • 將所有訂單根據金額劃分到 100 個桶里,第一個桶我們存儲金額在 1 元到 1000 元之內的訂單,第二桶存儲金額在 1001 元到 2000 元之內的訂單,以此類推。每一個桶對應一個文件,并且按照金額范圍的大小順序編號命名(00,01,02…99)
    • 理想情況
      • 訂單金額在 1 到 10 萬之間均勻分布,那訂單會被均勻劃分到 100 個文件中,每個小文件中存儲大約 100MB 的訂單數據
      • ==》可以將這 100 個小文件依次放到內存中,用快排來排序。
      • ==》 等所有文件都排好序之后,我們只需要按照文件編號,從小到大依次讀取每個小文件中的訂單數據,并將其寫入到一個文件中,那這個文件中存儲的就是按照金額從小到大排序的訂單數據了。
    • 實際情況:不均勻分布 ==》針對這些劃分之后還是比較大的文件,繼續劃分。==》直到所有文件都能讀入內存位置。
      • eg:訂單金額在 1 元到 1000 元之間的比較多,我們就將這個區間繼續劃分為 10 個小區間,1 元到 100元,101 元到 200 元,201 元到 300 元…901 元到 1000 元。

4、實現

#include <iostream> using namespace std;void BucketSort(int *A, int Max, int Size){int B[Max+1];int i,j,count = 0;memset(B, 0, (Max+1)*sizeof(int));for (i = 0; i < Size; i++) {j = A[i];B[j] += 1;}for (i = 0; i <= Max; i++) {if (B[i] > 0) {for (j = 0; j < B[i]; j++) {A[count] = i;count++;}}} }int main(int argc, const char * argv[]) {int A[]={1, 2, 2, 7, 4, 9, 3, 5};// 這里可以用一個O(n)的函數來實現,假如數組的手動輸入的,則在輸入的時候就可以獲取到。// 這里直接賦值是為了排出別的因素,看著簡單。int Max = 9; int Size = sizeof(A)/sizeof(int);BucketSort(A, Max, Size);for (int i = 0; i < Size; i++) {printf("%d ",A[i]);}printf("\n");return 0; }

二、計數排序(Counting Sort)

1、基本思想

基本思路:通過對待排序序列中的每種元素的個數進行計數,然后獲得每個元素在排序后的位置的信息的排序算法。

桶排序的特殊情況:桶的大小粒度不一樣,每個桶內的數據值都是相同,省去了桶內排序的時間

2、適用性

只適用于在數據范圍不大的場景中,而且只能給非負整數排序或在不改變相對大小的情況下可轉化為非負整數

3、實現

#include <iostream> #include <vector> using namespace std;void CountSort(vector<int> &arr, int maxVal) {int len = arr.size();if (len < 1)return;vector<int> count(maxVal+1, 0);vector<int> tmp(arr);for (auto x : arr)count[x]++;for (int i = 1; i <= maxVal; ++i)count[i] += count[i - 1];for (int i = len - 1; i >= 0; --i) {arr[count[tmp[i]] - 1] = tmp[i];count[tmp[i]]--; //注意這里要減1} }int main() {vector<int> arr = { 1,5,3,7,6,2,8,9,4,3,3 };int maxVal = 9;CountSort(arr,maxVal);for (auto x : arr)cout << x << " ";cout << endl;return 0; }

三、基數排序(Radix Sort)

1、基本思想

基數排序是桶排序的擴展。

基本思想:將整數按位數切割成不同的數字,然后按每個位數分別比較。

具體做法:將所有待比較數值統一為同樣的數位長度,數位較短的數前面補零。然后,從最低位開始,依次進行一次排序。這樣從最低位排序一直到最高位排序完成以后, 數列就變成一個有序序列。

2、不同的情形

  • 數字的排序中,若存在不同長度的問題 ==》在位數短的前面補零
  • 字符串的排序,若存在不同長度的問題 ==》位數不夠的可以在后面補“0”
    • 根據ASCII 值,所有字母都大于“0”,所以補“0”不會影響到原有的大小順序。
  • 其他含義序列中,若存在不同長度的問題 ==》具體情況具體分析

總結

以上是生活随笔為你收集整理的七、排序(3)——线性排序的全部內容,希望文章能夠幫你解決所遇到的問題。

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