1. 程式人生 > >《演算法導論》——桶排序

《演算法導論》——桶排序

《演算法導論》——桶排序

  1. 桶排序的思想就是把區間[0, 1)劃分成n個相同大小的子區間,每一個區間稱為桶(bucket)。然後,將n個輸入資料分佈到各個桶中去。因為輸入數均勻且獨立均勻分佈在[0, 1)上,所以一般不會有很多數落在一個桶中的情況。為得到結果,先對各個桶中的數進行排序,然後按次序把各個桶中的元素列出來即可。時間複雜度O(n).
  2. 在桶排序演算法中,假設輸入的是一個含n個元素的陣列A,且每個元素滿足0≤A[i]<1。另外,還需要一個輔助陣列B[0…n-1]來存放連結串列(桶),並假設可以用某種機制來維護這些表

虛擬碼
虛擬碼

c++程式碼

#include  "iostream"
#include "stdlib.h"
using namespace std;

struct Node
{
	double value;
	struct Node *next;
};

void BUCKET_SORT(double* array, int len)
{
	int count = 0;
	Node *bucket = new Node [len] ;     //開闢了一塊連續的儲存len個Node(頭節點)的陣列
	for (int i = 0; i < len; i++)		//初始化頭
	{
		bucket[i].value = 0;
		bucket[i].next = NULL;
	}
	for (int j = 0; j < len; j++)
	{
		Node *insert = new Node;
		insert->value = array[j];
		insert->next = NULL;
		int temp = array[j] * 10;
		if (bucket[temp].next == NULL) //連結串列中只有頭節點
		{
			bucket[temp].next = insert; //直接插入後
		}
		else                             //有多個節點,排序插入
		{
			Node *q = &bucket[temp];    //頭節點
			Node *p = bucket[temp].next;
			while (p!= NULL &&( p->value <= array[j]))
			{
				p = p->next;
				q = q->next;
			}
			q->next = insert;
			insert->next = p;
		}
	}
	for (int k = 0; k < len; k++)
	{
		Node *p = bucket[k].next;
		while (p != NULL)
		{
			array[count++] = p->value;
			p = p->next;
		}
	}

}
void main()
{
	double a[] = { 0.12, 0.13, 0.45, 0.53, 0.65, 0.48, 0.34, 0.45 };
	int length = sizeof(a) / sizeof(a[0]);
	BUCKET_SORT(a, length);
	for (int i = 0; i < length; i++)
	{
		cout << a[i] << " ";
	}
	cout << endl;
	system("pause");
}

桶排序也可以拓展至整數部分。


轉載
3. 桶排序在海量資料中的應用

一年的全國高考考生人數為500 萬,分數使用標準分,最低100 ,最高900 ,沒有小數,你把這500 萬元素的陣列排個序。

分析:對500W資料排序,如果基於比較的先進排序,平均比較次數為O(5000000*log5000000)≈1.112億。但是我們發現,這些資料都有特殊的條件: 100=<score<=900。那麼我們就可以考慮桶排序這樣一個“投機取巧”的辦法、讓其在毫秒級別就完成500萬排序。

方法:建立801(900-100)個桶。將每個考生的分數丟進f(score)=score-100的桶中。這個過程從頭到尾遍歷一遍資料只需要500W次。然後根據桶號大小依次將桶中數值輸出,即可以得到一個有序的序列。而且可以很容易的得到100分有**人,501分有*人。

實際上,桶排序對資料的條件有特殊要求,如果上面的分數不是從100-900,而是從0-2億,那麼分配2億個桶顯然是不可能的。所以桶排序有其侷限性,適合元素值集合並不大的情況。