zoukankan      html  css  js  c++  java
  • 【排序】基数排序

    基数排序

    • 对一组数组按个位、十位、百位、...、最高位上的数字对这组数组进行排序。

    算法流程

    • 获取所要排序的数组中最大的元素,方便提取出最大的位数
    int get_max(int a[],int n)
    {
         int maxn = a[0];
         for(int i=1;i<n;i++)
             maxn = max(maxn,a[i]);
         return max;
    }
    
    • 然后获取后,就可以依次从低位到高位向数组进行一次次的处理

      • 设exp为指数,代表当前要处理的位数,比如位数为1,exp=1;位数为2,exp=10;

      • 只要max/exp>0,就代表exp仍未达到数字的顶端

      for(exp=1;max/exp>0;exp*=10){
          CountSort(a,n,exp);
      }
      
    • 单个位置上的排序CountSort(int a[],int n,int exp)

      • 材料:

        • 桶排序:bucket[idx]表示的是idx在这个数组中有多少个

          桶排序改装:bucket[idx]表示的是以idx(0...9)在exp位有多少个

        • 前缀和:目的通过前缀和的处理将每个数字给区分开,也可以看成是把exp位上相同的数字的这一类数字锁在一定的区间,或者也可以看成赋予一定的权值给了这一类数字从而使得这一类数字与其他数字区分开来,并且通过同类的数字可以通过自己内部的减一操作来使得自己内部的数字也具有区分度。

          注意点,由于前缀和的关系,output如果不对其数组的下标进行减一的话,傻傻直接拿来用的话,是会和a的数组对不上的。

          for(int i=1;i<10;i++)
              bucket[i]+=bucket[i-1];
          
        • output数组:用来储存数组,并最终对a进行覆盖。

          output[bucket[a[i]/exp%10]] = a[i];
          
        • 同类的数字获取区分度

          bucket[a[i]/exp%10]--;
          
    • 在较低位置获取比较靠前的位置(相比于其他数字,会比较小),在较高位置的排序中也会优先被排序(这就保证了在高位上的相同数字的数字的大小的准确性)。

      比如(213,212在经过个位数的排序后会先变成212,213,然后在十位上的排序,212相对于213会获得较先被排序的机会)

    #include<bits/stdc++.h>
    using namespace std;
    int get_max(int a[],int alen)
    {
    	int maxn = a[0];
    	for(int i=1;i<alen;i++)
    	    maxn = max(maxn,a[i]);
    	return maxn;
    }
    
    void count_sort(int a[],int alen,int exp)
    {
    	int bucket[10],output[alen];
    	memset(bucket,0,sizeof(bucket));
        for(int i=0;i<alen;i++)
        {   
        	bucket[a[i]/exp%10]++;
    	}
        	
        
        for(int i=1;i<10;i++)
            bucket[i]+=bucket[i-1];
            
        for(int i=alen-1;i>=0;i--)//反着来 
        {
        	output[bucket[a[i]/exp%10]-1]=a[i];//这里有个减一,要使得output数组最终和buckets数组对上
        
    	    bucket[a[i]/exp%10]--;
    	}
    	
    	for(int i=0;i<alen;i++)
    		a[i] = output[i];
    }
    
    void radix_sort(int a[],int alen)
    {
    	int exp;
    	int maxn = get_max(a,alen);
    
    	for(exp=1;maxn/exp>0;exp*=10)
    		count_sort(a,alen,exp);
    }
    
    int main()
    {
    	int a[] = {53, 3, 542, 748, 14, 214, 154, 63, 616};
    	int alen = sizeof(a)/sizeof(a[0]);
    	
    	puts("radix_sort前");
    	for(int i=0;i<alen;i++)
    	    cout<<a[i]<<" ";
    	cout<<endl;
    	    
    	radix_sort(a,alen);
    	
    	puts("radix_sort后");
    	for(int i=0;i<alen;i++)
    	    cout<<a[i]<<" ";
        cout<<endl;
    	
    	return 0;	
    }
    
    

    其他

    获取数组长度

    int ilen = (sizeof(a)/sizeof(a[0]));
    

    参考

    基数排序

  • 相关阅读:
    再谈Linux内核中的RCU机制
    Linux下的crontab定时执行任务命令详解
    Linux 2.6内核中新的锁机制--RCU
    linux内核自锁旋spinlock常用宏解释
    Linux内核list/hlist解读
    Linux下0号进程的前世(init_task进程)今生(idle进程)----Linux进程的管理与调度(五)
    Linux下的进程类别(内核线程、轻量级进程和用户进程)以及其创建方式--Linux进程的管理与调度(四)
    Linux进程ID号--Linux进程的管理与调度(三)
    内核源码阅读(三)进程命名空间和用户命名的实现
    Linux的命名空间详解--Linux进程的管理与调度(二)
  • 原文地址:https://www.cnblogs.com/BeautifulWater/p/15105109.html
Copyright © 2011-2022 走看看