常見排序演算法(三)

来源:https://www.cnblogs.com/lemonyam/archive/2019/05/12/10832680.html
-Advertisement-
Play Games

計數排序: 1、一個非基於比較的排序演算法,該演算法於1954年由 Harold H. Seward 提出,它的優勢在於在對一定範圍內的整數排序, 其時間複雜度為Ο(n+k)(其中k是整數的範圍),快於任何比較排序演算法 2、步驟: a、找出給定整數序列的最大值 max 和最小值 min,創建大小為 ma ...


計數排序:

   1、一個非基於比較的排序演算法,該演算法於1954年由 Harold H. Seward 提出,它的優勢在於在對一定範圍內的整數排序,

     其時間複雜度為Ο(n+k)(其中k是整數的範圍),快於任何比較排序演算法

  2、步驟:

    a、找出給定整數序列的最大值 max 和最小值 min,創建大小為 max-min+1 的輔助空間,其值為 0

    b、最小的那個數下標為 0,最大數下標為 -1,其他數 num 的下標為 num-min

    c、根據遍歷所找到的數,在其相應下標處的值加一

    d、遍歷輔助空間,輸出對應下標的數,其輸出次數為下標處的值,即若輔助空間 temp[0] == 5,則輸出下標 0 對應的數 5 次

註:該演算法是以空間換時間,若待排序列不是整數,則最好不要使用,因為浮點數範圍比較大,即使像在 [0, 1) 這個區間也可以有極多個

#include <iostream>
#include <vector>
#include <algorithm>

void countSort(std::vector<int>& nums);

int main()
{
    std::vector<int> nums;
    int len = 0;
    std::cout<<"請輸入長度:";
    do {
        std::cin>>len;
        if (len <= 0)
            std::cerr<<"請輸入正整數:";
    } while (len <= 0);
    int num = 0;
    std::cout<<"輸入 "<<len<<" 個數: ";
    for (size_t i = 0; i < len; ++i) {
        std::cin>>num;
        nums.push_back(num);
    }
    std::cout<<"排序後的數組:";
    countSort(nums);
    
    system("pause");
    
    return 0;
}

void countSort(std::vector<int>& nums)
{
//    註意要使用 '*' 號,因為它們找到的都是位置,這兩個函數都包含在 algorithm 裡面 
    int max = *max_element(nums.begin(), nums.end());
    int min = *min_element(nums.begin(), nums.end());
    int size = max - min + 1;
//    創建輔助空間,初始化為 0 
    std::vector<int> temp(size, 0);
//    將對應下標的數出現次數加一 
    for (auto num : nums)
        temp[num-min] += 1; 
    for (int i = 0; i < size; ++i) {
        int count = temp[i];
//        根據次數輸出,我們在這裡沒有改變原序列的順序,
//        僅僅輸出排序後的序列,若要改變原序列,需要執行複製操作 
        while (count > 0) {
            std::cout<<i+min<<std::ends;
            count--;
        }
    }
    std::cout<<std::endl;
}
View Code

 

基數排序:

   1、基數排序是根據待排序列的元素的位來進行排序的,是一種非比較排序;它可以分為兩類:

      最低位優先法,簡稱 LSD 法:先從最低位開始排序,再對次低位排序,直到對最高位排序後得到一個有序序列

      最高位優先法,簡稱 MSD 法:先從最高位開始排序,再逐個對各分組按次高位進行子排序,迴圈直到最低位

      以下是 LSD 的動態演示圖

  2、步驟(LSD):

    a、根據待排序的元素的最多位數確定迴圈次數,如最多位的數位 12345,則迴圈 5 次

    b、創建 10 張空表,分別表示 0~9

    c、從最低位開始,根據位上的數值選擇放入的表,如 123 在最低位上的數為 3,則放到下標為 3 的表裡

    d、按順序將表裡的元素取出,替換原序列的數

    e、向高移動一位,重覆操作 c 和 d,直至迴圈次數

#include <iostream>
#include <vector>
#include <cmath>
#include <algorithm>
#include <cstdlib> 

int get_times(int num);
int get_digit(int num, int d);
void radixSort(std::vector<int>& nums);

int main()
{
    std::vector<int> nums;
    int len = 0;
    std::cout<<"請輸入長度:";
    do {
        std::cin>>len;
        if (len <= 0)
            std::cerr<<"請輸入正整數:";
    } while (len <= 0);
    int num = 0;
    std::cout<<"輸入 "<<len<<" 個數: ";
    for (size_t i = 0; i < len; ++i) {
        std::cin>>num;
        nums.push_back(num);
    }
    radixSort(nums);
    std::cout<<"排序後的數組:";
    for (int num : nums)
        std::cout<<num<<std::ends;
    std::cout<<std::endl;
    
    system("pause");
    
    return 0;
}

// 獲取第 d 位的數值
int get_digit(int num, int d)
{
    return int(num / pow(10, d)) % 10;
}

// 獲取需要迴圈的次數
int get_times(int num)
{
    int times = 0;
    while (num) {
        times++;
        num /= 10;
    }
    return times;
}

//沒有考慮負數的情況,如果需要的話可以使用兩個數組,一個存放正數,一個存放負數 
void radixSort(std::vector<int>& nums)
{
    int max = *max_element(nums.begin(), nums.end());
    int times = get_times(max);
    int len = nums.size();
    
    for (size_t i = 0; i < times; ++i) {
        std::vector<std::vector<int>> temp(10);
        for (int num : nums) {
            temp[get_digit(num, i)].push_back(num);
        }
                // 清除數組內容
        nums.clear();
                // 賦值
        for (auto vec : temp) {
            for (int num : vec) {
                nums.push_back(num);
            }
        }
    }
    return ;
}
View Code

 

桶排序:

  1、掃描選出待排序列的最大 max 和最小值 min,設有 k 個桶,則我們把區間 [min, max] 均勻地劃分為 k 個區間,

     每個區間就是一個桶,然後再將待排序列地元素分配到各自的桶里,即數值的大小在哪個區間就分配到哪

  2、對每個桶里的元素進行排序,可以選擇任意一種演算法

  3、將各個桶里的元素合併成一個大的有序序列

#include <iostream>
#include <vector>
#include <cstdlib>
#include <algorithm>

void bucketSort(std::vector<int>& num);

int main()
{
    std::vector<int> nums;
    int len = 0;
    std::cout<<"請輸入長度:";
    do {
        std::cin>>len;
        if (len <= 0)
            std::cerr<<"請輸入正整數:";
    } while (len <= 0);
    int num = 0;
    std::cout<<"輸入 "<<len<<" 個數: ";
    for (size_t i = 0; i < len; ++i) {
        std::cin>>num;
        nums.push_back(num);
    }
    
    std::cout<<"排序後的數組:";
    bucketSort(nums);
    
    system("pause");
    
    return 0;
}

//這個排序我沒有改變原序列的順序,僅僅只是輸出有序序列,若要改變原序列,請添加賦值操作 
void bucketSort(std::vector<int>& nums)
{
//    尋找最大最小值 
    int max = *max_element(nums.begin(), nums.end());
    int min = *min_element(nums.begin(), nums.end());
    
//    為方便起見,桶個數直接採用範圍大小 
    int buckets_num = max-min+1;
    std::vector<std::vector<int>> res(buckets_num);
    
    for (int num : nums) {
//        按數壓入 
        res[num-min].push_back(num);
    }
    
    for (auto vec : res) {
//        桶內排序 
        sort(vec.begin(), vec.end());
    }
        
    for (auto vec : res)
        for (int num : vec)
            std::cout<<num<<std::ends;
    std::cout<<std::endl;
        
    return ;
}
View Code

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 學習專業知識,不是都靠自己頑強的意志,更多的是需要跟別人交流,重要的就是跟比你強的人交流,加一些氛圍比較好的交流學習群,或者別人的一句話就能讓你茅塞頓開,學技術切記不能閉門造車,學習的大忌。 5.遇到問題搞不清楚,只能百度,然後自己一團糟 遇到問題的時候,不假思索「百度」,但是很多時候我們是浪費了大 ...
  • 首先這邊我先貼一個地址:https://www.adobe.com/cn/products/photoshop.html 安裝軟體,這裡就不贅述了,真的不會,可以百度^_^我當初就是百度的,哈哈 說到PS,作為前端開發的同學,一點都不陌生 前端需要掌握的PS知識,也不是很多 針對頁面佈局,我們前端需 ...
  • 一、字體類屬性: 1.字體類型: font-family:字體1,字體2,字體3; 常用寫法: font-family:"微軟雅黑",Arial; 註:a) 多個字體之間用逗號分隔; b)中文字體要放在雙引號中,英文字體由多個單片語成時也要加雙引號; c) 瀏覽器優先識別字體1,如果找不到字體1,識 ...
  • 1. 通過axios實現數據請求 vue.js預設沒有提供ajax功能的。 所以使用vue的時候,一般都會使用axios的插件來實現ajax與後端伺服器的數據交互。 註意,axios本質上就是javascript的ajax封裝,所以會被同源策略限制。 下載地址: axios提供發送請求的常用方法有兩 ...
  • 開 成 都 建 材 發 票微信775130892開 成 都 建 材 發 票微信775130892開 成 都 建 材 發 票微信775130892開 成 都 建 材 發 票微信775130892 開 成 都 建 材 發 票微信775130892開 成 都 建 材 發 票微信775130892開 成 都 ...
  • 裝飾模式概述 定義:動態地給一個對象增加一些附屬的職責。 裝飾裝飾,自然的理解就是在原有物品的基礎上,增加一些別的東西,讓它變得更令人滿意。且裝飾模式是在不改變對象本身的基礎上就行額外的增加,更加靈活。 比如買房,首先買的是個空房,隨後我們會放進去傢具,和各種生活中要用的東西,讓這個家變得更有家的味 ...
  • 支付系統一般需要對接多個支付渠道,一是為了保證系統的可靠性,不能因為單一渠道的問題影響整個支付系統。二是為了提高支付能力,不同渠道提供支付能力不同。三是為了降低支付成本。 對接多個支付渠道以後,為了可以正確選擇支付渠道支付,因此設計渠道路由系統。 從上圖可以看到路由系統功能其實很簡單,分發支付請求到 ...
  • 根據Python官方文檔,您可以強制垃圾收集器釋放未引用的記憶體gc.collect()。例: import gc gc.collect() 根據Python官方文檔,您可以強制垃圾收集器釋放未引用的記憶體gc.collect()。例: import gc gc.collect() 根據Python官方 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...