排序算法一 选择排序和冒泡排序


    最近在学习leetcode相关的课程,有个想法就是把自己的理解写下来,一个是方便自己查看,另外一个觉得这样子可以加深记忆。
    首先说一下,在评价一个算法的优劣的时候 一般情况之下我们会先根据算法的时间复杂度的指标进行一个判断,看算法是属于O(N 2) 或者O(N)等 ,指数数值越小则证明时间复杂度相对较低 但是当二者的指数指标相同的时候 就要根据实际运行的结果来判断到底哪一种算法更优。
    对算法的时间复杂度进行估计的时候 ,最终取的是按照最差的情况的时间复杂度作为我们算法的时间复杂度。

选择排序

排序原理

    选择排序就是每一轮遍历数组,找到其中最小的值,然后交换到此次遍历开始位置,经历N-1轮同样的操作(假设数组长度为N),让数组变得有序。
示意图如下:
1.遍历数组找到最小值
在这里插入图片描述
2.将最小值和这一轮遍历开始位置的元素交换
在这里插入图片描述

3.重复1和2步骤在这里插入图片描述

java代码实现

/**
     * 选择排序
     * @param arr
     */
    public static int[] selectionSort(int[] arr){
        if(arr == null || arr.length<2){
            return arr;
        }

        for (int i = 0; i < arr.length-1; i++) {//控制轮次
            int minIndex = i;
            for (int j = i+1; j < arr.length; j++) {//控制检索范围
                minIndex = arr[j] > arr[minIndex] ? minIndex:j;
            }
            swap(arr,i,minIndex);
        }

        return arr;
    }

    /**
     * 交换元素位置
     * @param arr
     * @param oldIndex
     * @param newIndex
     */
    public static void swap(int[] arr,int oldIndex,int newIndex){
        int temp = arr[oldIndex];
        arr[oldIndex] = arr[newIndex];
        arr[newIndex] = temp;
    }

    /**
     * 生成大小随机,内容随机的数组
     * @param maxArrSize
     * @param maxArrNumber
     * @return
     */
    public static int[] randomArr(int maxArrSize,int maxArrNumber){
        int randomSize = (int)(Math.random()*maxArrSize+1);
        int[] resultArr = new int[randomSize];
        for (int i = 0; i < randomSize; i++) {
            resultArr[i] = (int)(Math.random()*maxArrNumber);
        }
        return resultArr;
    }

    /**
     * 比较器参照方法
     * @param arr
     */
    public static int[] sort(int[] arr){
        Arrays.sort(arr);
        return arr;
    }

    /**
     * 对数器
     * @param compareCount
     * @param maxArrSize
     * @param maxArrNumber
     * @return
     */
    public static boolean compare(int compareCount,int maxArrSize,int maxArrNumber){
        for (int j = 0; j < compareCount; j++) {
            int[] arr = randomArr(maxArrSize,maxArrNumber);
            int[] sortArr1 = sort(arr);
            int[] sortArr2 = selectionSort(arr);

            for (int i = 0; i < arr.length; i++) {
                if(sortArr1[i] != sortArr2[i]){
                    return false;
                }
            }
        }

        return true;
    }

    public static void main(String[] args) {
        System.out.println(compare(10000000,10,100));
    }

    这里用了对数器,作用是用写出的排序和已有的排序,或者说实现起来比较容易的排序比较排序结果,如果在很多次测试中比较结果一致,那么可以认为这个新写出来的排序是没有问题的。

时间复杂度分析

    由上面画的排序示意图可看出,每轮参与的元素个数是依次递减的,从N,N-1,…,1,这是一个等差数列,Sn=n*a1+n(n-1)d/2=n+n(n-1)/2=1/2n2+1/2n,由于我们讨论的时间复杂度为最差时间复杂度(O),所以一般把最高次项作为该排序的时间复杂度,所以选择排序的时间复杂度为O(n2
选择排序在计算的过程中,只会用到固定几个变量,所以选择排序的额外空间复杂度
为O(1)

这里附加一个简单的时间复杂度计算方法的链接:时间复杂度简单计算.
额外空间复杂度的简单计算:
    如果程序运行过程中,不需要额外的数据结构,只是使用了额外的几个变量。那么额外空间复杂度为O(1);
    如果要申请一个和原数组大小一样的数组,那额外空间复杂度为O(n);

额外空间复杂度分析

选择排序只需要在满足交换元素的条件是使用固定几个变量,故选择排序的额外空间复杂度为O(1)。

稳定性分析

举个例子证明选择排序无法保证稳定,如图:
在这里插入图片描述
第一轮将1和2进行交换时,就打破了两个2之间的相对位置,故选择排序无法保证稳定。

冒泡排序

排序原理

    通过比较,不断的将较大的值交换到最后(遇到相等或者小于的情况则不进行交换),就像泡泡从水里冒出来以后越来越大一样。示意图如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
    总结一下冒泡排序的特点,当需要排序的数有N个时,需要进行N-1轮排序,每轮需要进行比较的次数为N-i-1次(本例子中i=0,1,2,i代表轮数)

java代码实现

public static int[] bubbleSort(int[] arr){
		if(arr==null||arr.length<2){
            return;
        }

        for (int i = arr.length-1; i >0; i--) {//控制轮数
            for (int j = 0; j < i; j++) {//控制比较次数
                if(arr[j]>arr[j+1]){
                    swap(arr,j,j+1);
                }
            }
        }
        return arr;
    }

//强调一下,使用这种交换方式必须保障集合内的元素在内存空间中的地址每个都不一致,不然会
使交换的两个值都变为0
    public static void swap(int[] arr,int oldIndex,int newIndex){
        arr[oldIndex] = arr[oldIndex] ^ arr[newIndex];
        //arr[newIndex] ^ arr[newIndex] = 0 异或的特性1:自己异或自己等于0
        //arr[oldIndex] ^ 0 = arr[oldIndex] 异或的特性2:任何数异或0等于自己
        arr[newIndex] = arr[oldIndex] ^ arr[newIndex];//实际上是 arr[oldIndex] ^ arr[newIndex] ^ arr[newIndex]
        arr[oldIndex] = arr[oldIndex] ^ arr[newIndex];//实际上是 arr[oldIndex] ^ arr[oldIndex] ^ arr[newIndex]
    }

时间复杂度分析

使用上述的简单判断时间复杂度方法,控制轮数的循环为N-1次,控制比较次数的循环N-1次(相对于本轮正在进行排序的元素个数来说),时间复杂度为O((N-1) × (N-1) × 1),去掉最高次项的常数,即时间复杂度为O(n2

额外空间复杂度分析

冒泡排序只需要在满足交换元素的条件是使用固定几个变量,故冒泡排序的额外空间复杂度为O(1)。

稳定性分析

冒泡排序在进行排序时,遇到相等的元素不进行交换,所以可以保证稳定。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值