常見排序算法(三)

計數排序:ios

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

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

  二、步驟:數組

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

    b、最小的那個數下標爲 0,最大數下標爲 -1,其餘數 num 的下標爲 num-min函數

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

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

注:該算法是以空間換時間,若待排序列不是整數,則最好不要使用,由於浮點數範圍比較大,即便像在 [0, 1) 這個區間也能夠有極多個blog

#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

 

基數排序:排序

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

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

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

      如下是 LSD 的動態演示圖

  二、步驟(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

 

桶排序:

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

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

  二、對每一個桶裏的元素進行排序,能夠選擇任意一種算法

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

#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
相關文章
相關標籤/搜索