线性时间排序算法-桶排序
桶排序有个条件是输入数据要服从均匀分布. 均匀分布为何物? 均匀分布分为连续型均匀分布与离散型均匀分布.
01
连续型均匀分布
如果连续型随机变量X满足概率密度函数为
则称X在[a, b]上服从连续均匀分布.图像为:
02
离散型均匀分布
离散型均匀分布是离散型概率分布,其中有限个数值拥有相同的概率。离散型均匀分布的另一种说法为“有限个结果,各结果的概率均相同”。例如均匀的骰子就是离散型均匀分布的例子,可能的值为1, 2, 3, 4, 5, 6,而每一个数字的概率都是1/6。图像为:
如果还是不懂, 请把小筑之前的数理统计2章内容搞定.咱们接着说桶排序
03
排序过程
桶排序是假设输入是由一个随机过程产生, 该过程将元素均匀、独立分布在[0,1)区间上. 将[0, 1)区间划分为n个相同大小的子区间, 我们就称为桶. 然后将n个输入数分别放在各个桶中. 因为输入数据是均匀、独立地分布在[0, 1)区间上, 所以一般情况不会出现很多数落在同一个桶中的情况. 然后我们对每个桶中的数进行排序, 最后遍历每个桶, 把每个桶中元素遍历出来即可. 桶排序原理看图:
04
Python代码
# coding=utf-8import mathfrom insert_sort import insert_sort # 这里引用了之前的插入排序def Bucket_Sort(A):"""桶排序"""n = len(A)B = [[] for _ in range(0, n)] # 这就是桶for i in range(0, n):B[math.floor(n*A[i])].append(A[i])C = [j for i in range(0, n) for j in insert_sort(B[i])]return Cif __name__ == '__main__':import numpy # 这里导入numpy生成均匀分布random_list = list(map(lambda x: round(x, 2), numpy.random.uniform(0, 1, 10)))print(Bucket_Sort(random_list))
05
C语言版
#include <stdio.h>#include <stdlib.h>#include "func_sort.h"//定义一个链表, 负责存储桶中的元素typedef struct node{float ele;struct node* next;} Node;void Bucket_Sort(float* A, int size, int bucket_size){//分配桶空间大小, 就是个二维数组只不过用二级指针表示Node** bucket = (Node**)malloc(bucket_size * sizeof(Node*));for (int i = 0; i < bucket_size; ++i){//为桶中每个链表分配的空间bucket[i] = (Node*)malloc(sizeof(Node));if (bucket[i] != NULL){//初始化桶中元素bucket[i]->ele = 0;bucket[i]->next = NULL;}else{return;}}for (int i = 0; i < size; ++i){//分配要放入桶中结点空间Node* node = (Node*)malloc(sizeof(node));if (node != NULL){//将数组的元素放入桶中node->ele = A[i];node->next = NULL;}else{return;}//这就是hash函数,可以分配到指定的桶索引int index = 10 * A[i];Node* p = bucket[index];if (p->ele == 0){//如果桶是空的则插入bucket[index]->next = node;}else{//若不空则一个一个找,插到比node元素大的前面,就是插入排序while ((p->next != NULL) && (p->next->ele <= node->ele))p = p->next;node->next = p->next;p->next = node;}//桶元素数量加1(bucket[index]->ele)++;}//打印排好序的数据for (int i = 0; i < bucket_size; ++i){for (Node* k = bucket[i]->next; k != NULL; k = k->next){printf("%.2f ", k->ele);}}printf("\n");//释放内存free(bucket);}//main.c#include <stdio.h>#include "func_sort.h"int main(){float A[] = { 0.78, 0.17, 0.39, 0.26, 0.72, 0.94, 0.21, 0.12, 0.23, 0.68 };int size = sizeof(A) / sizeof(float);Bucket_Sort(A, size, 10);return 0;}//func_sort.h#include<stdio.h>void insert_sort(int* a, int n);void Bucket_Sort(float* r, int size, int bucket_size);
桶排序C语言版用到了链表的数据结构, 链表的插入删除等操作以后咱们再聊. 代码每步已经注释好了, 有点基础都应该可以看懂.
06
总结
对于桶排序来说即使数据不是均匀分布的. 也可以在线性时间完成. 只要满足桶的大小的平方和与总的元素呈线性关系即可. 咱们今天就到这里.
如果喜欢本文请关注:
算法小筑
介绍计算机算法, C/C++及Python, 英语等等.
Official Account
