桶排序(穩定的排序算法)
桶排序 (Bucket sort)或所謂的箱排序,是一個排序算法,工作的原理是將數組分到有限數量的桶子裏。每個桶子再個別排序(有可能再使用別的排序算法或是以遞歸方式繼續使用桶排序進行排序)。
基本原理
把待排序序列中的數據根據函數映射方法分配到若干個桶中,在分別對各個桶進行排序,最後依次按順序取出桶中的數據。
適用於數據分配均勻,數據比較大,相對集中的情況。
映射函數
映射函數要根據數據情況合理的適用,最好可以達到每個桶中只有一個元素,使得時間複雜度最優,但是空間複雜度太高。
假設數據都爲3位的正整數,那麼對應的映射函數可以爲f(x)=x/100.即把百位相同的數劃到同一數據塊;
假設數據爲2和3位的正整數,那麼對應的映射函數可以爲f(x)=x/100.即把百位相同的數劃到同一數據塊;
如下圖:
代碼如下(C語言)
#include <stdio.h>
#include <stdlib.h>
/* struct node *next:鏈表裏用於指向下一個節點的指針,也就是指向下一個(節點)結構類型的指針。
struct node {} 是一種結構,有兩個成員,一個成員是 int 數據,另一個是指向下一個 node 結構的指針。 */
typedef struct node {
int num;
struct node *next;
}KeyNode;
void bucket_sort(int a[],int size,int bucket_size) {
int i,j;
//這是一個結構體指針的數組,數組內都是指針,還要分配內存,爲結構體指針數組分配大小爲bucket_size的內存空間
//使用二維指針表示二維數組,動態分配內存空間
KeyNode **bucket_num = (KeyNode **)malloc(bucket_size * sizeof(KeyNode*)); //分配行所用的空間
for(i = 0;i < bucket_size;i++) {
bucket_num[i] = (KeyNode*)malloc(sizeof(KeyNode)); //爲每個桶分配內存空間,分配列所用的空間
bucket_num[i]->num = 0; //記錄當前桶中的數量,初始化桶中數量爲0
bucket_num[i]->next = NULL; //爲結構體中的結構體指針變量初始化爲空
}
for(j = 0;j < size;j++) {
KeyNode *node = (KeyNode *)malloc(sizeof(KeyNode)); //定義一個結構體變量的指針
node->num = a[j];
node->next = NULL;
int index = a[j]/100; //映射函數計算桶號
KeyNode *p = bucket_num[index]; //初始化P成爲桶中數據鏈條的頭指針
//該桶中還沒有數據
if(p->num == 0)
{
bucket_num[index]->next = node;
(bucket_num[index]->num)++;
}else
{
//鏈表結構的插入排序
while(p->next != NULL && p->next->num <= node->num)
{
p = p->next;
}
node->next = p->next;
p->next = node;
(bucket_num[index]->num)++;
}
}
//打印結果
KeyNode * k = NULL; //定義一個空的結構體指針用於儲存輸出結果
for(i = 0;i < bucket_size;i++)
{
for(k = bucket_num[i]->next;k!=NULL;k=k->next)
{
printf("%d ",k->num);
}
}
printf("\n");
}
int main()
{
int a[] {491,381,615,917,716,13,217,419,19,138,61,917,176,113,27,419,419,38,615,917,16,113,217,419};
int size = sizeof(a)/sizeof(int); //計算數組長度
bucket_sort(a,size,10);
system("pause"); //防止控制檯閃退
}