桶排序

木木子!發表於2020-12-18

一.演算法思想

分治思想*

舉個例子:把1000士兵按身高分為四個方陣隊,你會如何劃分?

在這裡插入圖片描述

思考30秒後,往下看:
可能你會讓每個士兵報出身高,兩兩比較然後設定區域劃分?

這樣方法可以,但是會顯得很混亂,需要記錄特別多的資料。

換一種簡單的思路:

  1. 找出身高最高和最矮,並且記錄未Max,Min;
  2. (Max-Min)/4
  3. 記錄每個人的身高
  4. 分到相應的組(桶)中,直接丟進去,像丟到垃圾桶中一樣,此時是無序的
  5. 再把桶中垃圾分類(即把桶中資料排序)
  6. 最後把桶排序,當然桶中資料也按序拿出來

注:這裡的4是因為分為四組;容易出現的錯誤是,有人會以為把1000人分為四組,每一組250個人,但是這樣是不對的,你想身高這個並不是有規律的,大多人在170-175之間,所以並不是根據人數劃分,而是求出最大值和最小值,然後平均一下,只樣誤差會小一點,但是還會有誤差。

在這裡插入圖片描述
這樣就可以把對應資料丟到相應的桶中了。

這就是桶排序實現的過程;

當然會有比較正規的桶排序實現流程:

1. 設定一個定量的陣列當作空桶;
2. 遍歷輸入資料,並且把資料對映完之後,一個一個放到對應的桶裡去;
3. 對每個不是空的桶進行排序;
4. 從不是空的桶裡把排好序的資料拼接起來。

這就是基本實現流程了。
接下來就是程式碼實現了:
對於新手來說:如果對於語言的熟練度不是特別高的話,嘗試先寫出其核心演算法的虛擬碼;所謂虛擬碼,簡言之就是你能看懂,編譯軟體看不懂的程式碼:

for(i=0;i<n;i++)
   {
       求出最大值MAX,最小值MIN;
   }
   (MAX-MIN)/4=T
   A1=MIN+T;
   A2=A1+T;;
   A3=A2+T;
   A4=A3+T//求出四個組
   
  for(i=0;i<n;i++)
  {
  比較範圍  a[i]在A1裡面或者在A2,A3,A4中
  
  
 }

流程圖略了:但是附上一個有虛擬碼和流程圖的參考連結:
演算法流程圖

接下來程式碼實現了:
這裡實現的話,我採用最簡單的方式,參考《啊哈!演算法》一書。
假設一個編號就是一個桶,如果這個數有重複的,則這個桶加一;

#include<stdio.h>
int main()
{
	int book[1001];
	int i,j,t,n;
	
	for(i=0;i<=1000;i++)
       book[i]=0;
    scanf("%d",&n); 
     for(i=1;i<=n;i++)
     {
     	scanf("%d",&t); 
     	book[t]++;//計數 
     	
	 }
	 for(i=1000;i>=0;i--)//判斷編號 1000-0的桶 
	 {
	 	for(j=1;j<=book[i];j++)
	 	  printf("%d ",i);
	 	  
	 }
	 
	 getchar();//用於暫停程式,方便檢視結果 
	 return 0;
}

這裡採用的是一維陣列實現儲存資料以及儲存桶。這個缺點顯而易見,一維陣列必需大於最大的數,但是提前分配記憶體的判斷大小肯定很難,所以容易造成空間浪費,而且有的桶內資料可能很多,有的桶內資料很少,像身高來說,集中在165-170的肯定會最多,但是其他桶內就會少,但是分配的話還是一樣的多的記憶體,由此也造成一定的浪費。
引出:結構體方式
倘若你還沒學到,則到此為止,當然你也可以提前瞭解。

using namespace std;
struct ListNode
{
    double value;
    ListNode *next;
};

//桶排序主程式
void bucketSort(double* arr, int length)
{
    ListNode key[bucket_num];               // 對映關係: int key <- ElemNum/bucket_num 
    int number = 0;
    ListNode *p, *q;                               //插入節點臨時變數
    int counter = 0;
    for(int i = 0; i < bucket_num; i++)
    {
        key[i].value = 0;
        key[i].next = NULL;
    }

    for(int i = 0; i < length; i++)
    {
        ListNode *insert = new ListNode();
        insert->value = arr[i];
        insert->next = NULL;
        number = arr[i] * bucket_num;
        if(key[number].next == NULL)
        {
            key[number].next = insert;
        }
        else
        {
            p = &key[number];
            q = key[number].next;
            while((q != NULL) && (q->value <= arr[i]))
            {
                q = q->next;
                p = p->next;
            }
            insert->next = q;
            p->next = insert;
        }
    }
    for(int i = 0; i < bucket_num; i++)
    {
        p = key[i].next;
        if(p == NULL)
            continue;
        while(p != NULL)
        {
            arr[counter++] = p->value;
            p = p->next;
        }
    }
}

這個程式碼只是展示了思想。不可執行。

相關文章