排序算法

几种排序算法实现
一、冒泡排序
1.介绍
一种简单的排序算法,每次循环遍历都会找到极值。
2.过程
1)第一层循环 ,设变量 i : 从0 ~ 所有数数量-1。从前到后,找出极值不断放到后面。后面放好的极值是有序,不能再动
2)第二层循环,设变量j:从0~到所有数数量-1-i。注意,随着第一层循环的进行,第二层循环比较次数减少。
3.复杂度
1)时间复杂度
基本语句为最内层的交换处理,数量级为O(N^2)
2)空间复杂度
因为整个排序过程过程,只涉及两个数的交换,用到空间可以是两个数位置。所以空间复杂段为常数,O(1)
3)稳定性
稳定
4.实现

public class BubbleSort {
    static int[] ints = new int[]{3,7,2,4,6,5};
    public static void main(String[] args) {
        //外循环比较次数为数组长度-1
        for(int i = 0; i < ints.length - 1; i++){
            //随着外循环次数增加,要比较的次数减少
            //比较次数为数组长度-1-i
            for(int j = 0; j < ints.length - 1  - i; j++ ){
                if(ints[j] > ints[j + 1]){
                    exchange(j,j+1);
                }
            }
        }
        for (int anInt : ints) {
            System.out.print(anInt);
        }
    }
    private static void exchangeByLocatino(int a, int b) {
        //使用临时空间,交换
//        a = a ~ b;
        int tmp = ints[a];
        ints[a] = ints[b];
        ints[b] = tmp;
    }
    private  static void exchange(int a , int b){
        ints[a] = ints[a] ^ ints[b];
        ints[b] = ints[a] ^ ints[b];
        ints[a] = ints[a] ^ ints[b];
    }
}

二、插入排序
1.介绍
插入排序(Insertion sort)是一种简单直观且稳定的排序算法。如果有一个已经有序的数据序列,要求在这个已经排好的数据序列中插入一个数,但要求插入后此数据序列仍然有序,这个时候就要用到一种新的排序方法——插入排序法
2.过程
默认第一个数为排好序的队列。后面的数,依此插入有序队列中,保持队列顺序。
需要循环三层,
1)第一层循环,查找要插入前面有序队列的数。设变量i:从1开始变量到队尾。当发现第i个位置上的[i]小于前一个数[i-1],触发第二层循环
2)第二层循环,查找要插入前面有序队列中的位置。设遍历j:从0开始变量到i前面位置。当发现第j个位置的数大于i位置数时,触发第三层循环
3)第三层循环,插入位置j和i位置之间的数后移(包含j,不包含i),留出位置j,插入i位置数。注意这里要提前抽取i位置的数。
3.复杂度
1)时间复杂度
如果目标是把n个元素的序列升序排列,那么采用插入排序存在最好情况和最坏情况。最好情况就是,序列已经是升序排列了,在这种情况下,需要进行的比较操作需(n-1)次即可。最坏情况就是,序列是降序排列,那么此时需要进行的比较共有n(n-1)/2次。插入排序的赋值操作是比较操作的次数加上 (n-1)次(因为 n-1次循环中,每一次循环的比较都比赋值多一个,多在最后那一次比较并不带来赋值)。平均来说插入排序算法的时间复杂度为O(n^2)。因而,插入排序不适合对于数据量比较大的排序应用。但是,如果需要排序的数据量很小,例如,量级小于千,那么插入排序还是一个不错的选择
2) 空间复杂度
整个过程,也是移动两个数的位置,需要的空间位置为常量,所以数量级为O(1)
3)稳定性
稳定
4.实现

public class InsertSort {
    static int[] ints = new int[]{3,4,5,1,2,7};
    public static void main(String[] args) {
        //第一层循环,初始第一位有序,而后后面每一位跟前一位比较
        //i : 1 ~ lens -1
        for(int i = 1; i < ints.length -1; i++){
            //条件是后面数小于前面,a[i] < a[i-1]进入第二层循环
            //第二层循环是寻找a[i] 在前面的位置
            if(ints[i] < ints[i - 1]){
                for(int j = 0; j < i ; j++){
                    //j:从第一位开始遍历,一致遍历到i-1位置,如果碰到a[i] < a[j]就算找到,就要触发第三层,移动后面位置
                    if(ints[i] < ints[j]){
                        //移动位置 k: 从后向前,从i 开始 一直到 j.
                        //首先要提取出a[i],然后 依次 a[i] = a[i - 1], 一直到 a[j] = 提取出来的a[i]
                        int temp = ints[i];
                        for(int k = i; k > j; k--){
                            ints[k] = ints[k - 1];
                        }
                        ints[j] = temp;
                        //当找到插入位置后,后面的j就没必要进行下去了
                        break;
                    }
                }
            }
        }
        for(int i = 0; i < ints.length; i++){
            System.out.print(ints[i]);
        }
    }
}

参考:
复杂度分析
冒泡与插入排序分析
插入排序百科
插入排序时间复杂度计算过程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值