#include<stdio.h>
/*
应该设置几个桶,桶的个数buckerCount: 数组长度length/3 + 1
每个桶最多存放几个元素,桶的容量BuckerSize: 5个
如何确定到达了数组中的存放的最后一个元素
定义一个数组elemInBucket存放桶中元素个数(空间),或者:
找到数组中的最小元素,将桶中所有元素的都设置为defaultFigure = min - 1(时间)
这个程序使用的是第二种方法
如何确定每个桶中存放的元素的范围
找到最大最小值,计算差值d,根据差值计算每个桶之间的步长step
step = d / 桶的个数buckerCount + 1
第k个桶中的元素的范围应该是 min + (k-1) * step < elem < min + k * atep
如何判断应该存放到哪个桶中
k = (element - min) / step;
*/
void findPosiInBucket(int bucket[][5], int arr[], int k, int i, int defaultFigure, int bucketSize, int bucketCount);
void putInLeft(int bucket[][5], int arr[], int k, int i, int defaultFigure, int bucketSize, int bucketCount, int bucketLeftPosi);
void putInRight(int bucket[][5], int arr[], int k, int i, int defaultFigure, int bucketSize, int bucketCount, int bucketRightPosi);
void printBucket(int bucket[][5], int bucketSize, int bucketCount);
void bucketSort(int bucket[][5], int bucketCount, int bucketSize);
void sortForFive(int bucket[][5],int bucketCount,int bucketSize,int i);
void sortForThree(int bucket[][5],int bucketCount,int bucketSize,int i);
int main() {
//未排序前的数组
//int arr[] = {18, 11, 28, 45, 23, 50};
//int arr[] = {18, 16, 6, 87, 1, 67, 4, 66, 46, 41, 6, 67, 61, 64, 67, 16, 97, 97, 100, 11, 28, 45, 23, 50};
int arr[] = {18, 11, 28, 45, 23, 50, 27, 44, 71, 92};
//数组的长度
int length = sizeof(arr) / sizeof(int);
int bucketCount = length / 3 + 1;
int bucketSize = 5;
//输出排序前的数组
printf("排序前的数组:");
for(int i = 0; i < length; i++) {
printf(" %d ", arr[i]);
}
printf("\n");
//二维数组作为桶
int bucket[bucketCount][bucketSize];
//找到最大最小值
int max = arr[0];
int min = arr[0];
for(int i = 0; i < length; i++) {
if(arr[i] > max)
max = arr[i];
if(arr[i] < min)
min = arr[i];
}
//定义桶中的默认元素defaultFigure
int defaultFigure = min - 1;
//定义步长step
int step = (max - min) / bucketCount + 1;
//给桶中所有元素赋值为默认值
for(int i = 0; i < bucketCount; i++)
for(int j = 0; j < bucketSize; j++)
bucket[i][j] = defaultFigure;
//将数据放到对应的桶中
for(int i = 0; i < length; i++) {
int k = (arr[i] - min) / step; //应该放到下标为k的桶中
int temp = 0;
while(bucket[k][temp] != defaultFigure && temp++ < bucketSize); //找到数组下标为k的桶中的空位置
if(temp == bucketSize) { //如果temp等于bucketSize了说明桶中放不下这个元素了
findPosiInBucket(bucket, arr, k, i, defaultFigure, bucketSize, bucketCount);
} else { //正常情况
bucket[k][temp] = arr[i];
}
}
//对桶中的元素进行排序
bucketSort(bucket, bucketCount, bucketSize);
//各个桶之间的排序完成
//将桶中的数据放回原数组
int temp = 0; //存放arr数组下标
for(int i = 0; i < bucketCount; i++) {
for(int j = 0; j < bucketSize; j++) {
if(bucket[i][j] != defaultFigure)
arr[temp++] = bucket[i][j];
}
}
//输出排序后的数组
printf("排序后的数组:");
for(int i = 0; i < length; i++)
printf(" %d ", arr[i]);
printf("\n");
return 0;
}
void findPosiInBucket(int bucket[][5], int arr[], int k, int i, int defaultFigure, int bucketSize, int bucketCount) {
//找到左右两边距离最近的有位置的桶
int bucketLeftPosi = k - 1;
while(bucket[bucketLeftPosi][bucketSize - 1] != defaultFigure && bucketLeftPosi != 0) {
bucketLeftPosi--;
}
int bucketRightPosi = k + 1;
while(bucket[bucketRightPosi][bucketSize - 1] != defaultFigure && bucketRightPosi != bucketCount - 1) {
bucketRightPosi++;
}
if((k - bucketLeftPosi) <= (bucketRightPosi - k)) { //说明左边空位置近
putInLeft(bucket, arr, k, i, defaultFigure, bucketSize, bucketCount, bucketLeftPosi);
} else { //右边空出位置的桶近
putInRight(bucket, arr, k, i, defaultFigure, bucketSize, bucketCount, bucketRightPosi);
}
return ;
}
void putInLeft(int bucket[][5], int arr[], int k, int i, int defaultFigure, int bucketSize, int bucketCount, int bucketLeftPosi) {
//依次找到最小的数依次放过去
for(int j = 0; j < k - bucketLeftPosi; j++) {
//找到第k-j个桶里最小的数与数组元素交换
//找到最小的元素的位置
int minPosi = 0;
for(int t = 0; t < bucketSize && bucket[k - j][t] != defaultFigure; t++) {
if(bucket[k - j][t] < bucket[k - j][minPosi])
minPosi = t;
}
if(bucket[k - j][minPosi] > arr[i])
minPosi = -1;
//把最小的元素与数组交换
if(minPosi != -1) { //如果等于-1就不需要做处理
int temp = arr[i];
arr[i] = bucket[k - j][minPosi];
bucket[k - j][minPosi] = temp;
}
}
//当前桶有位置,把数组中的元素放进来
//找到空位置
int temp = 0;
while(bucket[bucketLeftPosi][temp] != defaultFigure && temp++ < bucketSize); //找到数组下标为k的桶中的空位置
//放进来数组元素
bucket[bucketLeftPosi][temp] = arr[i];
return ;
}
void putInRight(int bucket[][5], int arr[], int k, int i, int defaultFigure, int bucketSize, int bucketCount, int bucketRightPosi) {
//依次找到最大的数依次放过去
for(int j = 0; j < bucketRightPosi - k; j++) {
//找到第k+j个桶里最小的数与数组元素交换
//找到最小的元素的位置
int maxPosi = 0;
for(int t = 0; t < bucketSize && bucket[k + j][t] != defaultFigure; t++) {
if(bucket[k + j][t] < bucket[k + j][maxPosi])
maxPosi = t;
}
if(bucket[k + j][maxPosi] > arr[i])
maxPosi = -1;
//把最小的元素与数组交换
if(maxPosi != -1) { //如果等于-1就不需要做处理
int temp = arr[i];
arr[i] = bucket[k + j][maxPosi];
bucket[k + j][maxPosi] = temp;
}
}
//当前桶有位置,把数组中的元素放进来
//找到空位置
int temp = 0;
while(bucket[bucketRightPosi][temp] != defaultFigure && temp++ < bucketSize); //找到数组下标为k的桶中的空位置
//放进来数组元素
bucket[bucketRightPosi][temp] = arr[i];
return ;
}
void printBucket(int bucket[][5], int bucketSize, int bucketCount) {
for(int i = 0; i < bucketCount; i++) {
printf("第%d个桶中的数据:", i);
for(int j = 0; j < bucketSize; j++)
printf(" %d ", bucket[i][j]);
printf("\n");
}
printf("\n");
return ;
}
void bucketSort(int bucket[][5], int bucketCount, int bucketSize) {
for(int i = 0; i < bucketCount; i++) {
sortForFive(bucket, bucketCount, bucketSize,i);
sortForThree(bucket, bucketCount, bucketSize,i);
}
}
void sortForFive(int bucket[][5],int bucketCount,int bucketSize,int i) {
//定义五个元素中最大元素和最小元素的下标
int minPosi = 0;
int maxPosi = 0;
//找到五个元素中的最大和最小值,分别放到两侧
for(int j = 1; j < bucketSize; j++)
if(bucket[i][minPosi] > bucket[i][j])
minPosi = j;
//最大的元素放到右侧,最小的放到左侧,交换
int temp = 0;
if(minPosi != 0) {
temp = bucket[i][0];
bucket[i][0] = bucket[i][minPosi];
bucket[i][minPosi] = temp;
}
for(int j = 1; j < bucketSize; j++)
if(bucket[i][maxPosi] < bucket[i][j])
maxPosi = j;
if(maxPosi != bucketSize - 1) {
temp = bucket[i][bucketSize - 1];
bucket[i][bucketSize - 1] = bucket[i][maxPosi];
bucket[i][maxPosi] = temp;
}
}
void sortForThree(int bucket[][5],int bucketCount,int bucketSize,int i){
//找到中间三个个元素中的最大和最小值,分别放到两侧
int minPosi = 1;
int maxPosi = 0;
for(int j = 2; j < bucketSize - 1; j++) {
if(bucket[i][minPosi] > bucket[i][j])
minPosi = j;
if(bucket[i][maxPosi] < bucket[i][j])
maxPosi = j;
}
//最大的元素放到右侧,最小的放到左侧,交换
int temp = 0;
if(minPosi != 1) {
temp = bucket[i][1];
bucket[i][1] = bucket[i][minPosi];
bucket[i][minPosi] = temp;
}
if(maxPosi != bucketSize - 2) {
temp = bucket[i][bucketSize - 2];
bucket[i][bucketSize - 2] = bucket[i][maxPosi];
bucket[i][maxPosi] = temp;
}
}