• 算法


    总结

    算法分类

    十种常见排序算法可以分为两大类:

    • 比较类排序冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序 属于比较排序。在排序的最终结果里,元素之间的次序依赖于它们之间的比较。每个数都必须和其他数进行比较,才能确定自己的位置
      • 优势:适用于各种规模的数据,也不在乎数据的分布,都能进行排序。可以说,比较排序适用于一切需要排序的情况
      • 劣势:时间复杂度较高,为O(n2)或者O(nlogn),均高于线性时间O(n)
    • 非比较类排序计数排序、基数排序、桶排序则属于非比较排序。非比较排序是通过确定每个元素之前,应该有多少个元素来排序。针对数组arr,计算arr[i]之前有多少个元素,则唯一确定了arr[i]在排序后数组中的位置
      • 优势:非比较排序时间复杂度低,线性时间O(n)
      • 劣势:但由于非比较排序需要占用空间来确定唯一位置。所以对数据规模和数据分布有一定的要求。

    还有一种分类方法,是看待排序的记录是否全部被放置在内存中(注:本文讨论的都是内排序):

    • 内排序:所有待排序的记录都在内存中
    • 外排序:由于记录太多,不能同时放置在内存中,整个排序过程需要内外存之间多次交换数据才能进行。

    算法复杂度 + 空间复杂度

    图片名词解释:

    • n: 数据规模
    • k: “桶”的个数
    • In-place: 占用常数内存,不占用额外内存
    • Out-place: 占用额外内存
    • 稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。
    • 不稳定:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。
    • 时间复杂度:对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。
    • 空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数。 

    虽然同样是O(n2)的算法,但是平均时间来看,排序如下: 冒泡排序>选择排序>插入排序

    稳定性

    冒泡排序:稳定 -- 遇到相同的数组,选择不交换即可。

    选择排序:不稳定 -- 在一趟选择,如果当前元素(5)比一个元素(2)小,而该小的元素(2)又出现在一个和当前元素相等 的元素(5')后面,那么交换后稳定性就被破坏了。比较拗口,举个例子,序列5 8 5' 2 9,我们知道第一遍选择第1个元素5会和2交换,那么原序列中2个5的相对前后顺序就被破坏了2 8 5' 5 9,所以选择排序不是一个稳定的排序算法。

    必看:参考文章

    必看:十大经典排序算法最强总结(含JAVA代码实现)

     

    桶排序(请看这里)

    • 相对于计数排序,桶排序和计数排序的差别就在于处理相同数据的差别上。计数排序假设输入数据都属于一个小区间内的整数,而桶排序则是假设输入是由一个随时过程产生的,区间不确定。
    • 计算某元素应该放在哪个桶里:(num-min)/(max-min)表示这个数在(max-min)所占比重,再乘以桶的个数就得到对应桶的编号
    • 当元素均匀分布时,时间复杂度可以优化到O(n)

    请看文章:https://blog.csdn.net/u013521296/article/details/81625859?utm_source=blogxgwz5

     

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collections;
    
    /*
    ①找到待排序的数组A的min和max
    ②桶的数量(A.length)
    ③遍历数组A,把每个元素放到对应的桶中
    ④对每个桶的内部进行排序
    ⑤遍历每个桶
     */
    public class BucketSorting {
        public static void main(String[] args) {
            System.out.println("未排序前的A:");
            int[]A={0,30,0,28,19,30,30,28,1,0,29,10,20,20,10,19,29};
            System.out.println(Arrays.toString(A));
            System.out.println("使用桶排序后的A:");
            System.out.println(Arrays.toString(bucketsort(A)));
        }
    
        private static int[] bucketsort(int[] A) {
            int max=Integer.MIN_VALUE;
            int min=Integer.MAX_VALUE;
            //找最值
            for (int i = 0; i <A.length ; i++) {
                max=Math.max(max,A[i]);
                min=Math.min(min,A[i]);
            }
            //计算桶的数目
            int buckets=A.length;
            //把A中的元素分别放到对应的桶中,用ArrayList来实现桶
            ArrayList<ArrayList<Integer>> bucketArray=new ArrayList<>(buckets);
            for (int i = 0; i <buckets ; i++) {
                bucketArray.add(new ArrayList<Integer>());
    
            }
            //遍历元素,并放到桶里面
            for (int i = 0; i <A.length ; i++) {
                int bucketsNum=getBucket(A[i],buckets,min,max);
                bucketArray.get(bucketsNum).add(A[i]);
    
            }
            //对每个桶内部进行排序
            for(int i = 0; i < bucketArray.size(); i++){
           //每个桶内部,这里选择了快排(比较排序,这点很疑惑。你也可以递归使用桶排序)... Collections.sort()-->Arrays.sort()-->快排 Collections.sort(bucketArray.get(i)); } System.out.println(bucketArray.toString());
    //合并每个桶 int count=0; int[] result=new int[A.length]; for(int i = 0; i < bucketArray.size(); i++){ for (int j=0;j<bucketArray.get(i).size();j++){ result[count]=bucketArray.get(i).get(j); count++; } } return result; } //(num-min)/(max-min)表示这个数在(max-min)所占比重, //再乘以桶的个数就得到对应桶的编号 public static int getBucket(int num,int buckets,int min,int max){ return (int)((num-min)*(buckets-1)/(max-min)); }

     

    基数排序 vs 计数排序 vs 桶排序

    这三种排序算法都利用了桶的概念,但对桶的使用方法上有明显差异:

    基数排序:根据键值的每位数字来分配桶
    计数排序:每个桶只存储单一键值
    桶排序:每个桶存储一定范围的数值

  • 相关阅读:
    iOS最笨的办法实现无限轮播图(网络加载)
    iOS 动画基础总结篇
    ios 深入讲解iOS键盘一:控制键盘隐藏显示
    iOS开发之提交App中断出现:Cannot proceed with delivery: an existing transporter instance is currently uploading this package
    ios -仿微信有多级网页时,显示返回跟关闭按钮
    IOS启动页动画(uiview 淡入淡出效果 )2
    数量加减
    Swift泛型协议的N种用法
    一个swift版简单的用户名和密码输入textField
    Mac电脑上怎么设置环境变量
  • 原文地址:https://www.cnblogs.com/frankcui/p/11189720.html
Copyright © 2020-2023  润新知