數據結構與算法-桶排序

數據結構與算法 3.2.7

桶排序(Buchket Sort)

若是咱們有N個整數,範圍從1到M(或從0到M-1)。咱們留置一個數組,稱之爲Count,大小爲M,並初始化爲零。因而,Count有M個單元(或桶),開始他們都是空的。當Ai被讀入時Count[Ai]增1。在全部輸入都被讀進以後,
掃描數組Count,打印輸出排好序的表。該算法花費O(M + N)。
多趟桶排序是基於這樣一個場景:在0到N^p-1間的N個數,p是某個常數,此時使用桶排序,那麼就會形成桶數量過多。因此,對於此種問題,採用最低(有效)位優先的多趟桶排序能夠得出正確的結果。
下面例子說明10個數的多趟桶排序的具體作法,本例輸入{64, 8, 216, 512, 27, 729, 0, 1, 343, 125}。html

+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ 
    |  0  |  1  | 512 | 343 | 64  | 125 | 216 | 27  |  8  | 29  |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    |  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |  9  |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
                        圖3-24 第一次排序

    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ 
    |  8  |     | 729 |     |     |     |     |     |     |     |
    |  1  | 512 | 125 |     |     |     |     |     |     |     |
    |  0  | 216 |  27 |     | 343 |     | 64  |     |     |     |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ 
    |  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |  9  |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ 
                        圖3-25 第二次排序          

    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ 
    | 64  |     |     |     |     |     |     |     |     |     |
    | 27  |     |     |     |     |     |     |     |     |     |
    |  8  |     |     |     |     |     |     |     |     |     |
    |  1  |     |     |     |     |     |     |     |     |     |
    |  0  | 125 | 216 | 343 |     | 512 |     | 729 |     |     |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+ 
    |  0  |  1  |  2  |  3  |  4  |  5  |  6  |  7  |  8  |  9  |
    +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
                       圖3-26 第三次排序

多趟桶排序設計思路:

// 桶鏈表結構體
typedef struct Node{
	// 存儲的數值
	int Element;
	// 下一個桶指針
	PtrToNode Next;
} *PtrToNode; 

// [0-9]十個桶數組
PtrToNode Bucket[10];

參考資料

  1. 從新數據結構002:桶排序
  2. Python排序-桶排序與基數排序

頭文件(multi_bucket_sort.h)

struct Node;
typedef struct Node *PrtToNode;
typedef PrtToNode List;
typedef PrtToNode Position;

// 置空鏈表
List BMakeEmpty(List);
//測試一個鏈表是否爲空
int BIsEmpty(List);
// 在鏈表中查找第一個大於x的元素P
Position BFind(int, List);
// 刪除鏈表
void BDeleteList(List);
// 在元素P後插入X
void BInsertAfter(int, List, Position);
// 輸出鏈表
void BPrint(List);

源文件(multi_bucket_sort.c)

#include <stdio.h>
#include <stdlib.h>
#include "multi_bucket_sort.h"

#define FatalError( Str )   fprintf( stderr, "%s\n", Str ), exit( 1 )

/**
 * 桶鏈表結構體
 */
struct Node{
	int Element;
	Position Next;
};

/**
 * 置空鏈表
 * @param L
 * @return 
 */
List BMakeEmpty(List L) {
	if (L != NULL) {
		DeleteList(L);
	}

	L = malloc(sizeof(struct Node));
	if (L == NULL) {
		FatalError("Out of memory!");
	}
	L->Next= NULL;
	return L;
}

/**
 * 測試一個鏈表是否爲空
 * @param L
 * @return 
 */
int BIsEmpty(List L) {
	return L->Next == NULL;
}

/**
 * 在鏈表中查找第一個大於x的元素P
 * @param x
 * @param L
 * @return 
 */
Position BFind(int x, List L) {
	Position P;

	P = L;
	while(P->Next != NULL && P->Next->Element <= x) {
		P = P->Next;
	}
	return P;
}

/**
 * 刪除鏈表
 * @param L
 */
void BDeleteList(List L) {
	Position P, Tmp;

	P = L->Next;
	L->Next = NULL;
	while (P != NULL) {
		Tmp= P->Next;
		free(P);
		P = Tmp;
	}
}

/**
 * 在元素P後插入X
 * @param x
 * @param L
 * @param P
 */
void BInsertAfter(int x, List L, Position P) {
	if (P == NULL) {
		P = L;
	}

	Position TmpCell;
	TmpCell = malloc(sizeof(struct Node));
	if (TmpCell == NULL) {
		FatalError("Out of space!");
	}

	TmpCell->Element= x;
	TmpCell->Next	= P->Next;

	P->Next = TmpCell;
}

/**
 * 輸出鏈表 
 * @param L
 */
void BPrint(List L) {
	Position P;

	P = L->Next;
	while (P != NULL) {
		printf("|%d|%x|", P->Element, P->Next);
		P = P->Next;

		if (P != NULL) {
			printf("-->");
		}
	}
	printf("\n");
}

調用示例(多趟桶排序)

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include "ext/s13/multi_bucket_sort.h"

int main(int argc, char** argv) {
	List Bucket[10], Current;
	int i, j, k, x;

	// 預排序數組
	int a[10] = {64, 98, 21, 512, 23, 729, 30, 1, 343, 125};

	// 三趟排序
	for(i = 0; i < 3; i++) { 
		// 鏈表置空
		for (j = 0; j < 10; j++) {
			Bucket[j] = BMakeEmpty(NULL);
		}

		// 排序
		for (k = 0; k < 10; k++) {
			x = a[k];
			Current = Bucket[(int)(x/((int)pow(10, i)))%10];
			// 插入排序
			BInsertAfter(x, Current, BFind(x, Current));
		}
	}

	// 結果輸出
	for (j = 0; j < 10; j++) {
		if ( ! BIsEmpty(Bucket[j])) {
			BPrint(Bucket[j]);
		}
	}
	return (EXIT_SUCCESS);
}

輸出截圖

結果輸出

相關文章
相關標籤/搜索