1. 程式人生 > >【資料結構】非比較排序--計數排序和基數排序

【資料結構】非比較排序--計數排序和基數排序

非比較排序

  • 1、思想
    不需要進行元素之間的比較,交換,線上性的時間內完成排序。
  • 2、分類
    1)計數排序
    2)基數排序
  • 3、優缺點
    要求的空間比較多,是典型的以空間換時間的一種做法

計數排序

  • 1、原理
    這裡寫圖片描述
  • 2、程式碼實現
#include<iostream>
using namespace std; 

void CountSort(int* a,int n)
{
    //1、首先確定要開一個多大的用於統計的陣列
    int size = 0;
    int min = a[0];
    int max = a[0];
    for(int i = 0; i<n; i++)
    {
        if
(a[i] < min) min = a[i]; if(a[i] > max) max = a[i]; } size = max-min+1; //2、開始進行統計原陣列中對應下標出現的數 int* count = new int[size]; memset(count,0,sizeof(int)*size); for(int i = 0; i<n; i++) { count[a[i]-min]++; } //3、遍歷雜湊表,將count陣列中大於0的數對應出原陣列的值,
//寫入原陣列中 int j = 0; for(int i = 0; i<size; i++) { while(count[i]--) { a[j++] = i+min; } } delete[] count; } //測試函式 void TestCountSort() { int a[10] = {2,5,3,8,3,7,10,9,4,0}; int sz = sizeof(a)/sizeof(a[0]); CountSort(a,sz); for(int
i = 0; i<sz; i++) { cout<<a[i]<<" "; } cout<<endl; }
  • 4、時間複雜度和空間複雜度
    時間複雜度:O(N)
    空間複雜度:O(k)(其中K為要排序的陣列的範圍)

  • 5、優缺點
    1)缺點:由於計數排序的計數陣列的大小是取決於資料的範圍,那麼當要進行排序的資料範圍很大時,就需要大量的時間和記憶體。
    2)優點:
    A:無需進行比較,所以時間上快於任何的比較排序。
    B:適用於資料比較集中的資料排序

基數排序

  • 1、原理
    這裡寫圖片描述
  • 2、分類:
    LSD–從低位向高位排
    MSD–從高位向低位排
  • 3、程式碼實現
#include<iostream>
using namespace std; 
//給一個數,求這個數有多少位
int GetDigit(int* a,size_t n)
{
    int base = 10;
    int digit = 1;
    int num = 0;
    for(int i = 0; i<n; i++)
    {
        while(a[i] >= base)
        {
            digit++;
            base *= 10;
        }
    }

    return digit;
}
void LSDdigit(int* a,int n)
{
    int digit = GetDigit(a,n);  //得到位數
    int count[10] = {0};
    int start[10] = {0};
    int base = 1;
     //開闢一個新的陣列,用於存放一次排序後的數
    int*temp = new int[n];      
    while(digit--)
    {
        //首先按各位進行統計個位上的數出現的次數
        for(int i = 0; i<n; i++)
        {
            int num = (a[i]/base)%10;
            count[num]++;

        }
        start[0] = 0;
        for(int i = 1; i<10; i++)
        {
            start[i] = start[i-1]+count[i-1];
        }
        for(int i = 0; i<10; i++)
        {
            int num = (a[i]/base)%10;
            temp[start[num]++] = a[i];
            count[num]--;
        }
        for(int i = 0; i<10; i++)
        {
            a[i] = temp[i];
        }
        base *= 10;
    }
    delete[] temp;  

}

//測試函式
void TestLSDdigit()
{
    int a[10] = {73,22,93,43,55,14,28,65,39,81};
    int sz = sizeof(a)/sizeof(a[0]);
    LSDdigit(a,sz);
    for(int i = 0; i<sz; i++)
    {
        cout<<a[i]<<" ";
    }
    cout<<endl;
}
  • 4、時間複雜度和空間複雜度
    時間複雜度:O(N*digit)
    空間複雜度:O(N)
  • 5、適用性

    • 基數排序更適合用於對時間、字串等這些整體權值未知的資料進行排序。
    • 注意:基數排序如果從高位向低位排的話會很麻煩
  • 6、缺點
    由於是空間換取時間,按位進行排序,那麼每一位的數的位置可能會發生巨大的變化,目前硬體的快取不是很佔優勢,並且當記憶體比較寶貴的時候,就不要採取這種方式進行排序了。