【面试排序练习】——随笔记录(一)

本文介绍了两种线性时间复杂度的排序算法——计数排序和基数排序。计数排序适用于一定范围内的整数排序,通过设置多个桶来存放不同数值的元素;基数排序则按位数将元素分配到0-9的桶中,重复多次实现排序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

笔者之前的博客提到过七种经典排序算法,他们分别是:

  • 时间复杂度为:O(n²)的算法:冒泡排序,选择排序,插入排序
  • 时间复杂度为:O(n*㏒n)的算法:归并排序,快速排序,堆排序,希尔排序

那么本篇的内容将要介绍两种时间复杂度为O(n)的排序算法,分别是:计数排序基数排序

这两种算法不是基于比较的的排序算法,主要思想原形是基于桶排序,所谓的桶排序不是一种具体的实现而是一种思想。

一、计数排序

原理及思路:

例如现在需要将员工的身高进行从低到高排序,我们已知成年人的身高在100cm到300cm之间,这个时候我们可以设置100号到300号这200个桶,然后将员工根据身高的大小放入每一个桶中,然后依次到处100号到300号中的员工,这样最后的结果就有序了。

代码举例:

import java.util.*;

public class CountingSort {
    public int[] countingSort(int[] A, int n) {
        // write code here
        //如果数组为空,则无需排序
        if(A == null || n<1){
            return A;
        }
        //否则
        //首先我们需要设置一些桶,这里桶的数量我用 数组中的最大数减最小数决定
        //所以首先我们要取到数组中的最大数和最小数
        //声明两个变量表示
        int max = A[0];
        int min = A[0];
        //遍历数组,找出最大最小值
        for(int i=0;i<n;i++){
            if(max < A[i]){
                max = A[i];
            }
            if(min > A[i]){
                min = A[i];
            }
        }
        //根据最大最小值建立一个数组表示桶
        int temp[] = new int[max-min+1];
        //遍历数组将数组中的值放入桶中,同时桶数组记录数量,这时用桶数组的下标表示目标数组和最小值的差别,桶数组中存放数量
        for(int i=0;i<n;i++){
            temp[A[i]-min] += 1;
        }
        //存放完成后将桶中数字依次倒出,
        int index = 0; //表示下标
        for(int i=0;i<max-min+1;i++){
            while(temp[i] > 0){
                //从桶中取出一个树
                A[index++] = i + min;
                //桶中数量减一
                temp[i]--;
            }
        }
        return A;
    }

}

二、基数排序

原理及思路:

还是例如将公司员工的身高进行从低到高排序,我们已知身高用十进制表示,那么我们可以创建0号到9号一共十个桶,第一步现将所有元素的各位与桶编号对比,并将其放入对应的桶中,然后从0号到9号依次倒出;第二步,根据倒出来以后的顺序依次将十位数和桶编号比较,然后放入对应的桶中,再依次将桶中的元素倒出来;第三步,将百位数做和前面两次一样的操作,最后依次倒出桶中的元素,那么最后的数组就是排序后的结果。

代码举例:

import java.util.*;

public class RadixSort {
    public int[] radixSort(int[] A, int n) {
        // write code here
        if(A == null || n<1){
            return A;
        }
        //首先我们需要创建十个桶,每个桶中存放最多n个数
        int[][] temp = new int[10][n];
        //记录存放的数据数
        int[] count = new int[10];
        //定义变量表示身高区间
        int i = 1;
        while(i<1000){
            //遍历数组
            for(int j=0;j<n;j++){
                //求计算的位数,这里i是会变的
                int pos = A[j]/i%10;
                //将元素放入对应的桶
                temp[pos][count[pos]++] = A[j];
            }
            //设置参数表示下标
            int index = 0;
            //接下来要将桶中的元素倒出来,依次根据一维坐标和二维坐标取出
            for(int k=0;k<10;k++){
                for(int m=0;m<count[k];m++){
                    A[index++] = temp[k][m];
                }
                //全部取出后将计数数组置为0
                count[k] = 0;
            }
            //提高位数
            i*=10;
        }
        return A;
    }
}

 

经典排序总结

经典排序算法空间复杂度

1、O(1)

时间复杂度为O(n²):冒泡排序、插入排序、选择排序

时间复杂度为O(n*㏒n):堆排序,希尔排序

2、O(㏒n)~O(n)

快速排序,这个区间具体的值取决于被排列的数组的分布情况的好坏

3、O(n)

归并排序

4、O(m)

计数排序,基数排序。这里的m指的是桶的大小

 

经典排序算法的稳定性

1、不稳定的算法

希尔排序,堆排序,选择排序,快速排序

2、稳定的算法

冒泡排序,插入排序,归并排序,计数排序,基数排序,桶排序

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值