1.基数排序
这里的基数指的是位数:例如对十进制来说,指的是个位、十位、百位。
基本思想:
(1)首先设置号码为0-9的十个篮子;
(2)第一轮将序列的数字按照个位依次放置到对应号码的篮子中,并形成新的排序;
(3)第二轮在第一轮排序的基础上,按照十位依次放置到对应号码的篮子中,同样形成新的排序;
(4)依次类推,直到没有更好的位数,此时的排序即为最终的排序。
注意在放入篮子中的,不能改变元素本身相互之间的顺序,先遍历到的数字要先放进去。
具体示意图如下所示:
(图片来自https://www.cnblogs.com/ECJTUACM-873284962/p/6935506.html,侵权删)
第一轮排序后:
第二轮排序后:
代码实现:
public class JishuSort {
public static void main(String[] args) {
int[] a = {12,33,41,14,6,14};
sort(a);
for(int i = 0;i<a.length;i++)
System.out.println(a[i]);
}
public static void sort(int[] a){
int len = a.length;
int max = a[0];
//选出最大值,根据最大值得到最高位,计算循环次数
for(int i=1;i<len;i++){
if(a[i]>max){
max = a[i];
}
}
//定义二维数组记录排序存放排序数据,即十个篮子
int[][] buckets = new int[10][len];
//记录buckets中每个组里存放的数据个数,即每个篮子中放入的数据个数
int[] num = new int[10];
//使用1、10、100、1000等来记录位数
int h = 1;
while(h<max){
//依次将数据放置到对应编号的篮子中
for(int i = 0;i<len;i++){
buckets[(a[i]/h)%10][num[(a[i]/h)%10]] = a[i];
num[(a[i]/h)%10]++;
}
//将每轮排序后的结果返回到a
int n = 0;
for(int i = 0;i<10;i++){
if(num[i]!=0){
for(int j = 0;j<num[i];j++){
a[n] = buckets[i][j];
n++;
}
}
//注意每轮排序后需要将num置为0,即将篮子清空
num[i] = 0;
}
//增加位数
h*=10;
}
}
}
2.桶排序
基本思想:根据数据的范围将其分配到不同的桶中,桶中的元素各自排序,最后合并到一起。
算法步骤:
(1)初始化建立一定数量的buckets;
(2)遍历原始序列,根据元素大小放置到对应的bucket中;
(3)对非空的buckets中的元素进行排序;
(4)按照顺序返回buckets中的元素到原始数组中即可完成排序。
可参看如下例子:
(图片来自https://img-blog.csdn.net/20150929092136858,侵权删)
代码实现:
参考:https://www.cnblogs.com/zer0Black/p/6169858.html
import java.util.ArrayList;
import java.util.Collections;
public class BucketSort {
public static void main(String[] args) {
int[] a = {12,33,41,14,6,14};
sort(a);
for(int i = 0;i<a.length;i++)
System.out.println(a[i]);
}
public static void sort(int[] a){
int max = a[0];
int min = a[0];
int len = a.length;
//根据序列中的最大值和最小值确定bucket的数量
for(int i = 1;i<len;i++){
if(a[i] > max)
max = a[i];
if(a[i] < min)
min = a[i];
}
//bucket的数量blen
int blen = (max-min)/len + 1;
//初始化bucket
ArrayList<ArrayList<Integer>> buckets = new ArrayList<ArrayList<Integer>>(blen);
for(int i = 0;i<blen;i++){
buckets.add(new ArrayList<Integer>());
}
//在每个bucket中存放元素
for(int i = 0;i<len;i++){
buckets.get((a[i]-min)/len).add(a[i]);
}
//对bucket内元素进行排序
for(int i=0;i<blen;i++){
Collections.sort(buckets.get(i));
}
System.out.println(buckets.toString());
}
}
3.计数排序
基本思想:对每一个元素x,确定小于x的元素个数。因此我们就可以直接把x放到最终输出数组中的相应位置上。
算法步骤:
(1)设置辅助数组count,长度为max-min+1;
(2)遍历无序序列,将元素依次放置到count数组对应序号的位置上,得到每个元素出现的次数,例如a[i]出现了3次,则count [a[i] - min] = 3;
(3)遍历count数组,使得count[i] = count[i]+count[i-1],由此得到小于i的元素的个数,即i在整个无序序列中应该拍在第count[i]位;
(4)建立临时数组temp,遍历无序序列,如a[i],根据count得到小于a[i]的个数,将a[i]直接放置到temp对应位置上。
代码实现:
public class CountSort {
public static void main(String[] args) {
int[] a = {12,33,41,14,6,14};
int[] re = sort(a);
for(int i = 0;i<re.length;i++)
System.out.println(re[i]);
}
public static int[] sort(int[] a){
int max = a[0];
int min = a[0];
int len = a.length;
//计算序列最大值和最下值,确定count数组的长度为max-min+1
for(int i = 1;i<len;i++){
if(a[i]>max)
max = a[i];
if(a[i]<min)
min = a[i];
}
int[] count = new int[max-min+1];
int[] temp = new int[len];//临时数组
//计算每个元素出现的次数
for(int i=0;i<len;i++){
count[a[i]-min]++;
}
//计算小于某元素的元素的个数
for(int i=1;i<max-min+1;i++){
count[i] = count[i] + count[i-1];
}
//将元素放置到temp对应位置中,并且记得每放置一个元素,对应的count--;
for(int i = 0;i<len;i++){
if(count[a[i]-min]!=0){
temp[count[a[i]-min]-1] = a[i];
count[a[i]-min]--;
}
}
return temp;
}
}