从0开始学算法--排序(1.8桶排序)

怎甘沉沦 提交于 2019-12-01 14:03:08

算法理解:

  桶排序是对计数排序的一种优化,在计数排序中x应该放在计数数组下表为x的位置上,这样如果重复数字较少,计数数组每个位置的利用率就非常小。

  桶排序是将一系列大小近似的数字放在一个位置(每个桶维护一条有序的链表),这样提高每个位置的利用率,以提高效率.

以A【】={1,21,23,41,49}为例

假设每个桶里有10中元素,那么桶排序的结构如下图所示。

 

 

 

 

#include <algorithm>
#include <iostream>
#include <cstring>
#include <vector>
#include <cstdio>
#include <cmath>
#include <queue>

using namespace std;

const int maxn=1e5+10;

typedef struct node{
    int key;
    struct node* next;
}KeyNode;

void bucket_sort(int keys[],int size,int bucket_size){
    KeyNode **bucket_table=(KeyNode**)malloc(bucket_size*sizeof(KeyNode*));
    for(int i=0;i<bucket_size;i++){    //初始化桶
        bucket_table[i]=(KeyNode*)malloc(sizeof(KeyNode));
        bucket_table[i]->key=0;
        bucket_table[i]->next=NULL;
    }
    for(int i=0;i<size;i++){
        KeyNode* node=(KeyNode*)malloc(sizeof(KeyNode));
        node->key=keys[i];
        node->next=NULL;
        int index=keys[i]/10;//给数据分类的方法(关系到排序速度,很重要)
        KeyNode *p=bucket_table[index];
        if(p->key==0){
            p->next=node;
            p->key++;
        }
        else{
            while(p->next!=NULL&&p->next->key<=node->key){//=的时候后来的元素会排在后面
                p=p->next;
            }
            node->next=p->next;
            p->next=node;
            (bucket_table[index]->key)++;
        }
    }
    KeyNode* k=NULL;
    for(int i=0;i<bucket_size;i++){
        for(k=bucket_table[i]->next;k!=NULL;k=k->next){
            printf("%d ",k->key);
        }
    }
}
int main(){
    int n;int a[maxn];
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d",&a[i]);
    }
    bucket_sort(a,n,100);
    return 0;
}

例一:

  给你一个数组,找到差值绝对值最小是多少?

解:最简单的思路就是先排序,之后遍历一遍,时间复杂度是O(nlogn),那么能否O(n)求解呢,是可以的。

  如果有n个数,那么我们把最大到最小值之间的数字分到n-1个桶里,必然会有两个数字在一个桶里(鸽巢原理)(抽屉原理),最小值值可能是这个桶的最小值和上一个桶的最大值的差,或者两个在同个桶的数字,对于不同的桶我们遍历一遍,对于相同的桶又回到了最初的问题,即给你一个数组,找到差值绝对值最小是多少?,这样相同的桶就递归处理,即可使效率达到比较高的状态。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!