桶排序(BucketSort)

时间:2021-06-19 14:26:37

1 桶排序核心思想是 根据数据规模n划分 m个相同大小的区间 (每个区间为一个桶,桶可理解为容器)

2 每个桶存储区间内的元素(区间为半开区间 例如[0,10) 或者 [200,300) )

3 将n个元素按照规定范围分布到各个桶中去

4 对每个桶中的元素进行排序,排序方法可根据需要,选择快速排序,或者归并排序,或者插入排序

5 依次从每个桶中取出元素,按顺序放入到最初的输出序列中(相当于把所有的桶中的元素合并到一起)

6 桶可以通过数据结构链表实现

7 基于一个前提,待排序的n个元素大小介于0~k 之间的整数  或者是(0, 1)的浮点数也可(算法导论8.4的例子)

8 桶排序的时间代价,假设有m个桶,则每个桶的元素为n/m

 当辅助函数为冒泡排序O(n2)  ,桶排序为 O(n)+mO((n/m)2)

当辅助函数为快速排序时O(nlgn),  桶排序为 O(n)+mO(n/m log(n/m))

9 通常桶越多,执行效率越快,即省时间,但是桶越多,空间消耗就越大,是一种通过空间换时间的方式

注意:代码前部分为辅助代码

辅助类:链表Link

辅助函数:冒泡排序BubbleSort

 #include <iostream>
#include <crtdbg.h>
#include <cstring>
using namespace std; typedef int DataType;
//建立链表
class Link
{
private:
struct Node
{
DataType data;
Node *next;
};
Node *head; //哨兵位
public:
Link()
{
Init();
}
~Link()
{
Delete();
}
void Init()
{
head = new Node;
head->next = NULL;
}
void Delete()
{
for (Node *p = head; p != NULL;)
{
Node *pTemp = p->next;
delete p;
p = pTemp;
}
head = NULL;
}
void Print()
{
for (Node *p = head->next; p != NULL; p = p->next)
{
cout << p->data << endl;
}
}
//顺序插入 考虑两种情况 1.空表 2.当插入值是最大值的时候
void SortInsert(DataType data)
{
Node *p = head;
do
{
if (p->next == NULL || p->next->data > data)
{
Node *pNew = new Node;
pNew->data = data;
pNew->next = p->next;
p->next = pNew; return;
}
p = p->next;
} while (true);
}
//尾插法直接插入
void Insert(DataType data)
{
Node *p = head;
while(p->next != NULL)
{
p = p->next;
} Node *pNew = new Node;
pNew->data = data;
pNew->next = NULL;
p->next = pNew;
}
bool Empty()
{
return head->next == NULL;
}
//去掉首结点并返回首结点的值
int ExtractDate()
{
if (! Empty())
{
DataType data = head->next->data;
Node *p = head->next;
Node *pFirst = p->next; delete p;
p = NULL; head->next = pFirst;
return data;
}
return -;
}
};
//冒泡排序
void BubbleSort(int *a, int size)
{
for(int i=; i<size; ++i)
{
for (int j=; j<size--i; ++j)
{
if (a[j] > a[j+])
{
int tmp = a[j];
a[j] = a[j+];
a[j+] = tmp;
}
}
}
}
//基于一个前提:待排序的n个元素大小是介于 0~k 之间的整数
//array待排序数组,result辅助数组存储排序结果,k为允许的最大整数
void BucketSort(int array[], int result[], int size, int k)
{
Link *Bucket = new Link[]; //建立桶
int sectionSize = k/; //记录区间大小
int index=; //记录区间下标 //方法1:一般步骤
//按照范围把array中的每个值放入相应的桶中
for(int i=; i<size; ++i)
{
index = array[i]/sectionSize;
Bucket[index].Insert(array[i]); //为保证稳定性,链表使用了尾插法插入
}
//遍历每个桶,取出桶中的元素,放入辅助数组result,并排序
int j= , m=;
for (int i=; i<; ++i)
{
m = j; //记录已排好序的数组元素大小
while(!Bucket[i].Empty())
{
result[j++] = Bucket[i].ExtractDate();
} //可根据实际情况选择快速排序,堆排序等,此处简单起见选择冒泡排序
BubbleSort(result+m, j-m);
} //方法2:使用链表特性,在插入链表的同时排序
//for(int i=0; i<size; ++i)
//{
// index = array[i]/sectionSize;
// Bucket[index].SortInsert(array[i]);
//}
//int j=0;
//for(int i=0; i<5; ++i)
//{
// while(!Bucket[i].Empty())
// {
// result[j++] = Bucket[i].ExtractDate();
// }
//} delete [] Bucket;
} void main()
{
//检测是否有内存泄露 需要加头文件#include <crtdbg.h>
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); int Array[] = {, , , , , , , , , };
int Result[] = {}; BucketSort(Array, Result, sizeof(Array)/sizeof(Array[]), ); for (int i= ; i < ; ++i)
{
cout << Result[i] << "\n";
} system("pause");
}

(转载请注明作者和出处^_*  Seven++ http://www.cnblogs.com/sevenPP/  )