插入排序、希尔排序、选择排序、堆排序、冒泡排序!

说到前面的小小基础:什么是稳定性?

两个相等的数据通过排序之后,相对位置不发生变化,则称该种排序具有稳定性,是稳定的!

插入排序

基本思想:将整个数据分为有序区间和无序区间,每次选择无序区间的第一个数据插入到有序区间的合适的位置。

举个栗子!!

初始数据:3  2  5  7  6  3  4  9

前部分为有序区间,后部分为无序区间。

排序结果为:2  3  5  7  6  3  4  9

(省略……)

再次排序为:2  3  5  6  7  3  4  9

再次排序为:2  3  3  5  6  7  4  9

最后排序结果为:2  3  3  4  5  6  7  9

以上,两个相同数据3的位置通过插入排序能确保相对位置不变,所以插入排序具备稳定性

public static void insertSort(long[] array) {
    for (int i = 0; i < array.length - 1; i++) {
        // 有序 [0, i]
        // 无序 [i + 1, array.length)
        // 无序区间中的第一个数据是 [i + 1]

        long key = array[i + 1];    //无序区间的第一个元素

        // 依次在有序区间进行比较 [i, 0]
        int j;
        for (j = i; j >= 0; j--) {
            // [j] 就是需要和 key 进行比较的数
            if (key < array[j]) {
                array[j + 1] = array[j];
            } else {
                break;
            }
        }
        array[j + 1] = key;
    }
}

时间复杂度最好情况下为:O(n)  //数据有序的情况下

时间复杂度最坏情况下为:O(n^2)  //数据逆序的情况下

时间复杂度平均情况下为:O(n^2)  

空间复杂度为:O(1)                稳定!

希尔排序

又称“缩小增量法”,基本思想:选定一个整数,把待排序部分分成gap个小组,每个间距为n的数据为一组,按小组排序。将gap越取越小,直到gap==1,此时排序完成。

举个栗子!!

初始数据为:9  2  3  6  4  7  8  1  5  3;//令前面的3为a,后面的3为b

当gap==5时,9  2  3  6  4  7  1  5  3;  (分为五组,每个颜色表示一组)

按小组排序之后结果为:7  2  1  5  3  9  8  3  6  4;(再将其分为3组)//此时b在a之前

gap==3时,7  2  1  5  3  9  8  3  6  4;

按小组排序之后为:4  2  1  5  3  6  7  3  9  8;(分为两组)//此时b在a之前

gap==2时,4  2  1  5  3  6  7  3  9  8

按小组排序之后结果为:1  2  3  3  4  5  7  6  9  8;//此时b在a之前

此时gap==1时,作出排序为:1  2  3  3  4  5  6  7  8  9;//此时b在a之前   

以上,两个相同数据3的位置通过希尔排序并不能确保相对位置不变,所以希尔排序不具备稳定性

public static void shellSort(long[]  array){
   int gap = array.length/2;          

    while(gap>=1){                        //循环截止条件:gap<1
       insertSortGap(array,gap); 
       if(gap==1){                       //gap==1时,排序完成
          break;
       }
       gap = gap/2;                      //将gap逐渐减小,即将分组逐渐扩大
    }
}

private static void inserSortGap(long[] array,int gap){
	for(int i = gap;i<array.length;i++){
	   long key = array[i];
	   int j;
	   for(j=i-gap;j>=0;j=j-gap){
	      if(key<array[j]){
	         array[j+gap] = array[j];
	      }else{
	         break;
	      }
	   }
	   array[j+gap] = key;
	}
}

时间复杂度最好情况下为:O(n)  //数据有序的情况下

时间复杂度最坏情况下为:O(n^2)  

时间复杂度平均情况下为:O(n^1.3)  

空间复杂度为:O(1)            不稳定!

选择排序

将数据分为有序区间和无序区间,每次选出无序区间的最大值,存放在有序区间的最后(或最前),直到无序区间内再无数据。

举个栗子!!

初始数据:9  2  3  6  4  7  8  1  5  3

前部分为无序,后部分为有序,则:2  3  6  4  7  8  1  5  3  9

继续排序:2  3  6  4  7   1  5  3  8  9

继续排序:2  3  6  4  1  5  3  7  8  9

(此处省略,以此类推……)

当排序到数据3时,相对位置靠前的3将被放置在有序区间的最前面,所以两个数据的相对位置会发生改变,所以选择排序不具备稳定性

    public static void selectSort(long[] array) {
        // 一共多少次选择的过程
        for (int i = 0; i < array.length - 1; i++) {
            // 无序区间: [0, array.length - i)
            // 有序区间: [array.length - i , array.length)

            int maxIndex = 0;     // <-- 假设最大的数就是 array[0]
            for (int j = 1; j < array.length - i; j++) {
                if (array[j] > array[maxIndex]) {
                    maxIndex = j;
                }
            }
            // 期望 maxIndex 指向无序区间的最大的数的下标

            swap(array, maxIndex, array.length - i - 1);
        }
    }

时间复杂度为:O(n^2)  

空间复杂度为:O(1)            不稳定!

堆排序

基本原理也是选择排序,不通过遍历找到区间最大值,而是通过堆来找到区间最大值

ps:升序建大堆,降序建小堆!!!

   public static void heapSort(long[] array) {
        // 1. 建大堆
        createHeap(array, array.length);

        // 2. 进行选择的过程,一共需要 array.length - 1 组
        for (int i = 0; i < array.length - 1; i++) {
            // 无序:[0, array.length - i)
            swap(array, 0, array.length - i - 1);
            // 无序:[0, array.length - i - 1)
            adjustDown(array, array.length - i - 1, 0);
        }
    }

    private static void adjustDown(long[] array, int size, int index) {
        while (2 * index + 1 < size) {
            int maxIndex = 2 * index + 1;
            if (maxIndex + 1 < size && array[maxIndex + 1] > array[maxIndex]) {
                maxIndex++;
            }

            if (array[index] >= array[maxIndex]) {
                break;
            }

            swap(array, index, maxIndex);

            index = maxIndex;
        }
    }

    private static void createHeap(long[] array, int size) {
        for (int i = (size - 2) / 2; i >= 0; i--) {
            adjustDown(array, size, i);
        }
    }

时间复杂度为:O(n*log(n))  

空间复杂度为:O(1)            不稳定!

冒泡排序

基本思路,通过相邻数的比较,将最大数冒泡到无序区间的最后面,持续这个过程,直到数据有序

    public static void bubbleSort(long[] array) {

        // 需要多少次冒泡过程
        for (int i = 0; i < array.length - 1; i++) {
            // 无序: [0, array.length - i)
            // 有序: [array.length - i, array.length)

            // 每次冒泡之前,假设数组已经有序
            boolean isSorted = true;

            // 进行冒泡过程
            for (int j = 0; j < array.length - i - 1; j++) {
                if (array[j] > array[j + 1]) {
                    swap(array, j, j + 1);

                    isSorted = false;
                }
            }

            if (isSorted) {
                break;
            }
        }
    }

 

时间复杂度最好情况下为:O(n)  //数据有序的情况下

时间复杂度最坏情况下为:O(n^2) //数据逆序的 情况下

时间复杂度平均情况下为:O(n^2)  

空间复杂度为:O(1)            稳定!

 

 

快速排序和归并排序 

请看下集!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值