桶排序,计数排序算法

计数排序:

桶排序:www.roading.org/algorithm/introductiontoalgorithm

算法模型:

1,桶排序假设待排的一组数统一分布在一个范围[m....n],将这一范围划分为几个子范围,也就是桶bucket。

  例如,如何将0---999范围的数,划分到10个桶中?范围中数的个数用K表示,那么K/10=1000/10=100,就是每个桶装100个元素,即[0..99]装到第一个桶中,[100..199]装到第二个桶中,。。。以此类推。

  怎么判断一个数组该放到哪个桶中呢?例如整形元素a[i]=342,a[i]/100=342/100=3,就是说342得放到第(3+1)=4桶中

2,将待排序的一组数,分别放到这些子桶中。(可以采用插入排序的过程,在放入桶的过程中进行排序;也可以分配好后,利用stdlib.h中的qsort函数进行快速排序);

3,最后将各个桶中的数据有序的合并起来。

时间复杂度分析:https://www.byvoid.com/blog/sort-radix

对于整数序列A,元素的最小值不小于0,最大值不大于K。假设我们由M个桶,第i个桶Bucket[i]存储的i*K/M~(i+1)*K/M之间的数字。

如果数据是期望平均分配的,则每个桶中的元素平均个数就N/M。

  如果对每个桶中的元素采用快速排序,每次排序的的复杂度为O(N/M *  log(N/M))。

则总的时间复杂度为O(N)+O(M)*O(N/M *  log(N/M)) = O(N + Nlog(N/M)) = O(N+NlogN - NlogM),就是说M越接近N时,桶排序的时间复杂度就可近似认为是O(N)。这时桶的数量也就越多。

//伪代码
Bucket-Sort(A)
    let B[0..n-1] be a new array
    n = A.lenghtS
    for i = 0 to n - 1
        make B[i] an empty list
    for i = 1 to n
        insert A[i] into list B[nA[i]]
    for i = 0 to n - 1
        sort list B[i] with insertion sort
    concatenate the lists B[0], B[1]....B[n - 1] togather in order

  来自https://zh.wikipedia.org/wiki/%E6%A1%B6%E6%8E%92%E5%BA%8F

class A{
public:
 ///
    const int BUCKET_NUM = 10;
    ListNode *insert(ListNode *head, int val){
        ListNode dummyNode(-1);
        ListNode *newNode = new ListNode(val);
        ListNode *prev,*curr;
        dummyNode.next = head;
        prev = &dummyNode;
        curr = head;
        while(curr && curr->val <= val){
            prev = curr;
            curr = curr->next;
        }///find location to insert; prev->next
        newNode->next = curr;
        prev->next = newNode;
        return dummyNode.next;
    }

    ListNode *mergebucket(ListNode *head1,ListNode *head2){
        ListNode dummy(-1);
        ListNode *h = &dummy;
        while(head1 && head2){
            if(head1->val <= head2->val){
                h->next = head1;
                head1 = head1->next;
            }else{
                h->next = head2;
                head2 = head2->next;
            }
            h = h->next;
        }
        if(head1) h->next = head1;
        if(head2) h->next = head2;
        return dummy.next;
    }

    void BucketSort(int n,int arr[]){
        vector<ListNode*> buckets(BUCKET_NUM,nullptr);
        for(int i = 0;i<n;i++){
            int index = arr[i]%BUCKET_NUM;
            ListNode *head = buckets[index];
            buckets[index] = insert(head,arr[i]);
        }///
        ListNode *head = buckets[0];
        for(int i = 1;i<BUCKET_NUM;i++){
            head = mergebucket(head,buckets[i]);
        }

        for(int i = 0;i<n;i++){
            arr[i] = head->val;
            head = head->next;
        }
    }///

    void test(ListNode *head){
        int *a = new int[15];
        for(int i = 0;i<15;i++){
            a[i] = rand()%15+1;
        }
        for(int i = 0;i<15;i++){
            cout<<a[i]<<" ";
        }cout<<endl;
        BucketSort(15,a);
        for(int i = 0;i<15;i++){
            cout<<a[i]<<" ";
        }cout<<endl;
    }
};

基数排序

基数排序(Radix Sort)。计数排序和桶排序都只是在研究一个关键字的排序,现在我们来讨论有多个关键字的排序问题。

假设我们有一些二元组(a,b),要对它们进行以a为首要关键字,b的次要关键字的排序。我们可以先把它们先按照首要关键字排序,分成首要关键字相 同的若干堆。然后,在按照次要关键值分别对每一堆进行单独排序。最后再把这些堆串连到一起,使首要关键字较小的一堆排在上面。按这种方式的基数排序称为MSD(Most Significant Dight)排序。

第二种方式是从最低有效关键字开始排序,称为LSD(Least Significant Dight)排序。首先对所有的数据按照次要关键字排序,然后对所有的数据按照首要关键字排序。要注意的是,使用的排序算法必须是稳定的,否则就会取消前一次排序的结果。由于不需要分堆对每堆单独排序,LSD方法往往比MSD简单而开销小。下文介绍的方法全部是基于LSD的。

通常计数排序要用到计数排序或桶排序。

下面利用桶排序 对  二元组进行 基数排序。

时间: 2024-10-27 07:50:34

桶排序,计数排序算法的相关文章

算法导论-- 线性时间排序(计数排序、基数排序、桶排序)

线性时间排序 前面介绍的几种排序,都是能够在复杂度nlg(n)时间内排序n个数的算法,这些算法都是通过比较来决定它们的顺序,这类算法叫做比较排序 .下面介绍的几种算法用运算去排序,且它们的复杂度是线性时间. -------------------------------------- 1.计数排序 计数排序采用的方法是:对每个元素x,去确定小于x的元素的个数,从而就可以知道元素x在输出数组中的哪个位置了. 计数排序的一个重要性质是它是稳定的,即对于相同的两个数,排序后,还会保持它们在输入数组中的

java-数组排序--计数排序、桶排序、基数排序

计数排序引入 不难发现不论是冒泡排序还是插入排序,其排序方法都是通过对每一个数进行两两比较进行排序的,这种方法称为比较排序,实际上对每个数的两两比较严重影响了其效率,理论上比较排序时间复杂度的最低下限为nlog(n),即任何比较排序的时间复杂度将不会低于nlog(n),那么有没有方法能不经过数列比较就能使数列排序呢 ,她们的时间复杂度又是多少呢??? 计数排序就是一个非比较排序的算法,一如鱼与熊掌不可兼得,她使用了牺牲空间换时间的方法,使的时间复杂度可以达到Ο(n+k) 假设我们有一个数列arr

【算法导论-学习笔记】以线性时间增长的排序——计数排序

计数排序是一种能够达到运行时间能够线性时间θ(n)的排序算法.在排序算法里算是最快的算法之一,当然,他有很强烈的前提.下面开始介绍一下技术排序(Counting Sort). 算法思想 计数排序假设n个输入元素中的每一个都是介于0到k之间的整数,此处k为某个整数.这样可以用一个数组C[0..k]来记录待排序数组里元素的数量.当k=O(n)时,计数排序的运行时间为θ(n). 注:关于C[0..k],用键值对描述的话,待排序元素是键,相同元素的个数是值.例:待排序数组<2,3 , 6,4 , 1 ,

算法学习-02(希尔排序,计数排序,桶排序,基数排序)

希尔排序 # 希尔排序 # 希尔排序是对插入排序的升级改造 # 它的大致流程是 # 1.将长度为n的序列 分为d = n//2组 # 2.使每一组变的有序 # 3.将序列分为 d1 = d // 2 组 # 4.将每一组变的有序 # 5.直到最后 d 小于等于 0 def inster_sort_gap(li,gap): for i in range(gap,len(li)): tmp = li[i] j = i - gap while j >= 0 and tmp > li[j]: li[j

有Leetcode中一道题,谈桶排序,基数排序和计数排序

几种非比较排序 在LeetCode中有个题目叫Maximum Gap,是求一个非排序的正数数列中按顺序排列后的最大间隔.这个题用桶排序和基数排序都可以实现.下面说一下桶排序.基数排序和计数排序这三种非比较排序. 桶排序 这种排序的主要思想是,把数列分配到多个桶中,然后再在各个桶中使用排序算法进行排序,当然也可以继续使用桶排序. 假设数组的最大值是A,最小值是B,长度是L,则每个桶的大小可以是S=Max(1,(A-B)/(L-1))则可以分为(A-B)/S+1个桶. 对于数列中的数字x,用(x-B

桶排序和计数排序

突然想自己写个桶排序,然后做课后题又发现了计数排序,觉得挺有趣的.不过书上都没有给代码,所以就自己写了一下代码,超级烂0 0下面先简单介绍下这两种排序 桶排序 桶排序,就是根据散列的思想进行数据的排序.假设有M个桶,采用最简单的hash(key)=key,这样无需比较,就可以把数存入相应的桶中.针对冲突排解问题,此时查找链的方式显然不再适用,采用独立链法,把每个桶以链表的形式存储雷同元素,定义相同元素的偏序,这样能实现排序的稳定性.桶排序完全采用了简单的哈希策略,是比较容易理解的.同时,完全摒弃

常见的排序算法(四)( 归并排序,计数排序 , 基数排序)

 归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用.将已有序的子序列合并,得到完全有序的序列:即先使每个子序列有序,再使子序列段间有序.若将两个有序表合并成一个有序表,称为二路归并. (如果读者不太了解什么叫分治法,可以去看看<算法导论>第一二章.) 归并过程为:比较a[i]和a[j]的大小,若a[i]≤a[j],则将第一个有序表中的元素a[i]复制到r[k]中,并令i和k分别加上1:否则将第

线性排序之基数排序,桶排序,计数排序

基数排序 计数排序 桶排序 基数排序,桶排序,计数排序是三种线性排序方法,突破了比较排序的O(nlogn)的限制.但是只适用于特定的情况. 基数排序 以下为维基百科的描述: 基数排序 : 将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零.然后,从最低位开始,依次进行一次排序.这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列. 基数排序的方式可以采用LSD(Least significant digital)或MSD(Most significant digit

经典排序算法 - 计数排序Counting sort

经典排序算法 - 计数排序Counting sort 注意与基数排序区分,这是两个不同的排序 计数排序的过程类似小学选班干部的过程,如某某人10票,作者9票,那某某人是班长,作者是副班长 大体分两部分,第一部分是拉选票和投票,第二部分是根据你的票数入桶 看下具体的过程,一共需要三个数组,分别是待排数组,票箱数组,和桶数组 var unsorted = new int[] { 6, 2, 4, 1, 5, 9 };  //待排数组 var ballot = new int[unsorted.Len

冒泡排序,快速排序,归并排序,插入排序,希尔排序,堆排序,计数排序,桶排序,基数排序

选择排序,冒泡排序,快速排序,归并排序,插入排序,希尔排序,计数排序,桶排序,基数排序 以上是一些常用的排序算法. 选择排序 for(int i = 0; i < n; i++) { int minval = a[i]; int minid = i; for (int j = i+1; j < n; j++) { if (a[j] < minval) { minid = j; minval = a[j]; } } swap(a[i], a[minid]); } 最简单的就是选择排序,就是