1. 程式人生 > >排序演算法之 計數排序 及其時間複雜度和空間複雜度

排序演算法之 計數排序 及其時間複雜度和空間複雜度

       計數排序是一個非基於比較的排序演算法,該演算法於1954年由 Harold H. Seward 提出。它的優勢在於在對一定範圍內的整數排序時,它的複雜度為Ο(n+k)(其中k是整數的範圍),快於任何比較排序演算法。

演算法分析

        主要思想:據array陣列元素的值進行排序,然後統計大於某元素的元素個數,最後就可以得到某元素的合適位置;比如:array[4] = 9;統計下小於array[4]的元素個數為:8;所以array[4] = 9 應該放在元素的第8個位置;         主要步驟:        1、根據array陣列,把相應的元素值對應到tmpArray的位置上;
2、然後根據tmpArray陣列元素進行統計大於array陣列各個元素的個數; 3、最後根據上一步統計到的元素,為array元素找到合適的位置,暫時存放到tmp陣列中;         如下圖所示:array 是待排序的陣列;tmpArray 是相當於桶的概念; tmp 是臨時陣列,儲存array排好序的陣列;

        

        注意:計數排序對輸入元素有嚴格要求,因為array元素值被用來當作tmpArray陣列的下標,所以如果array的元素值為100的話,那麼tmpArray陣列就要申請101(包括0,也就是 mix - min + 1)。

程式碼實現

<pre name="code" class="cpp">#include<stdio.h>
#include<stdlib.h>
 
 void print_array(int *array, int length)
 {
     int index = 0;
     printf("array:\n");
     for(; index < length; index++){
         printf(" %d,", *(array+index));
     }   
     printf("\n\n");
 }
 
 void countSort(int *array, int length)
 {
   /*
     int *tmpArray = (int*)malloc(sizeof(int)*length);
     int i, j, count;
 
     for (i = 0; i < length; i++) tmpArray[i] = 0;
         
     for (i = 0; i < length; i++){
         for (count = 0, j = 0; j < length; j++){
             if (array[i] < array[j])count++;
         }               
         while(tmpArray[count])count++;
         tmpArray[count] = array[i];
     }   
 
     for (i = 0; i < length; i++)array[i] = tmpArray[i];
 
     free(tmpArray);
  */

     int *tmpArray = (int*)malloc(sizeof(int)*(length+1));//申請記憶體空間,記得大小為length + 1(因為array元素值為 0~9)
     int tmp[length];
     int i, j, k;
 
     for (i = 0; i < length; i++){ // 初始化陣列
         tmpArray[i] = 0;  
         tmp[i] = 0;
     }   
 
     for (i = 0; i < length; i++) tmpArray[array[i]]++; // 表示該桶內有多少個元素
 
     for (i = 1; i <= length; i++) tmpArray[i] += tmpArray[i-1];// 統計大於該元素的元素個數
     
     for (i = length; i > 0; i--){// 這是核心程式碼了,可以理解為把array陣列中的元素存放到合適的位置
         tmp[tmpArray[array[i-1]]-1] = array[i-1];
         tmpArray[array[i-1]]--; // 解決一個桶內有多個元素
     }   
 
     for (i = 0; i < length; i++) array[i] = tmp[i];// 把有序元素放回到array陣列中
 
     free(tmpArray);// 是否空間

 }
 int main(void)
 {
 //  int array[] = {12, 1, 32, 201, 9987, 5, 10, 10090, 123, 453};
     int array[] = {2, 1, 3, 0, 9, 5, 1, 7, 4};
     int length = (sizeof(array)) / (sizeof(array[1]));
     print_array(array, length);
     countSort(array, length);
     print_array(array, length);
 
     return 0;
 }

        執行結果:

        

時間複雜度

        時間複雜度可以很好的看出了就是:O( n );

空間複雜度

        空間複雜度也可以很好的看出來:O( n );

總結

        計數排序的時間複雜度和空間複雜度都是非常有效的,但是該演算法對輸入的元素有限制要求,所以並不是所有的排序都使用該演算法;最好的是0~9之間的數值差不會很大的資料元素間比較;有人會說這個沒多大用,但是在後面的基數排序中會看到,這可以算是基數排序中的一個基礎;         若有不正確之處,望大家指正,共同學習!謝謝!!!