学习数据结构笔记(6)====>八大排序算法(Sort Algorithm)[冒泡,选择,插入,快速,希尔,基数,归并,堆排序]

B站学习传送门–>尚硅谷Java数据结构与java算法(Java数据结构与算法)


写在前面
数组结构可视化在线网站地址 ===>数据结构可视化在线

排序算法: 把一组数据,依指定顺序进行排列的过程.

在这里插入图片描述

1.时间复杂度概述

时间频度

时间频度(T(n)) 算法中语句的执行次数

案例
时间频度为 (n+1);
这里的n就是100;
加1是因为最后在循环时还要再判断一次;

public class Demo01 {
    public static void main(String[] args) {
        int total = 0;
        int end = 100;
        for (int i = 1; i <= end; i++) {
            total +=i;
        }
        System.out.println(total);//5050
    }
}

但是若直接简化写为;
时间频度就变成 1 ;因为仅执行一次

public class Demo01 {
    public static void main(String[] args) {
        int total = 0;
        int end = 100;
        total =(end +1 )* end/2;
        System.out.println(total);//5050
    }
}

实际上,常数项可以忽略

在这里插入图片描述

低阶的次数项也可以忽略

在这里插入图片描述

在同等次方的条件下,和次方项前面的系数有关系;去掉系数后;这个就接近了

在这里插入图片描述

时间复杂度

在计算机科学中,时间复杂性,又称时间复杂度,算法的时间复杂度是一个函数,它定性描述该算法的运行时间。这是一个代表算法输入值的字符串的长度的函数。时间复杂度常用大O符号表述,不包括这个函数的低阶项和首项系数。使用这种方式时,时间复杂度可被称为是渐近的,亦即考察输入值大小趋近无穷时的情况。
一般情况下,算法中基本操作重复执行的次数是问题规模n的某个函数,用T(n)表示,若有某个辅助函数f(n),使得当n趋近于无穷大时,T(n)/f (n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数。记作T(n)=O(f(n)),称O(f(n)) 为算法的渐进时间复杂度,简称时间复杂度。

时间频度不同,时间复杂度可能相同
例: T(n) = n² + 6n+2 与 T(n) = 2n² + 5n+2
时间复杂度都可写为 O(n²)

Ο(1)<Ο(log₂n)<Ο(n)<Ο(nlog₂n)<Ο(n²)<Ο(n³)< Ο(n^k) <Ο(2ⁿ)
时间复杂度增大,效率变低

在这里插入图片描述

常数阶 Ο(1):
只要里面没有循环之类的复杂运算,代码再多也都是O(1)常数阶;
不会因为某个变量的增加而增加消耗的时间

对数阶: Ο(log₂n)
案例:比如说要计算下面这个循环次数;
在while循环内;每次都给 i *2 ;条件是i<1024;
1024 = 2^10; 即 n = 2^10; 那么对应的就是 log₂n = 10; 执行的次数为10次;
即时间复杂度为对数阶O(log₂n);
当然,这个根据实际情况会发生改变; 若 在循环中变为 i = i * 5 ;那么时间复杂度也就是O(log5n)

public class Demo02 {
    public static void main(String[] args) {
        int i = 1;
        int n =1024;
        //num:用来计数
        int num = 0;

        while (i<n){
            i = i * 2 ;
            num++;
        }
        System.out.println("执行次数->"+num); //执行次数->10
    }
}

线性阶:O(n)
单层循环的话,按照循环的规模来决定; 时间复杂度就是O(n)
案例;它的执行次数为 T(n) = n +1 ;
忽略掉常数项 ; 时间复杂度其实就是O(n);
在本案例中循环的规模n=10;那么它时间复杂度为O(10);
当n变为20时,它也就是O(20);总的来说,时间复杂度就是线性阶的O(n)

public class Demo03 {
    public static void main(String[] args) {
        int w =0;
        int num = 0;
        int n =10;
        for (int i = 0; i <= n ; i++) {
            w = num;
            num ++;
        }
        System.out.println(w);  // 10 
        System.out.println("执行次数->"+num);//执行次数->11
    }
}

线性对数阶Ο(nlog₂n)
实际上就是让时间复杂度为O(log₂n)的再循环n次
案例;这里执行次数就是 T(n) = (n+1) * (log₂n)

public class Demo04 {
    public static void main(String[] args) {
        int n =1024;
        int i ;
        //num:用来计数
        int num = 0;
        for (int m = 0; m <= n; m++) {
            i =1;
            while (i<n){
                i = i * 2 ;
                num++;
            }
        }
        System.out.println("执行次数->"+num); //执行次数->10250  (1024+1) * 10
    }
}

平方阶Ο(n²)
实际就是把时间复杂度为O(n)的再嵌套一层循环;即双层循环;也可写作O( m* n)
案例

public class Demo05 {
    public static void main(String[] args) {

        int w =0;
        int num = 0;
        int m =10;
        int n =10;
        for (int i = 1; i <= m ; i++) {
            for (int j = 1; j <= n; j++) {
                w = num;
                num ++;
            }
        }
        System.out.println(w);  // 99
        System.out.println("执行次数->"+num);//执行次数->100
    }
}

平均&最差时间复杂度

在这里插入图片描述

2.冒泡排序

按照提前设定的规则 (由小到大 / 由大到小) ;比较前后两个相邻元素的大小;若逆序了,就发生交换;

例如需要完成由小到大冒泡排序:29,10,14,37,14,3
图示:–>

在这里插入图片描述

初始的理解过程

总共经过数组的(长度-1)次大的交换过程;即 5 次;
其实每次大的排序结束后就有一个最大的值固定下来了;所以循环次数会比上一次的少一次
(1)
10 -> 29 -> 14 -> 37 -> 14 -> 3
10 -> 14 -> 29 -> 37 -> 14 -> 3
10 -> 14 -> 29 -> 37 -> 14 -> 3
10 -> 14 -> 29 -> 14 -> 37 -> 3
10 -> 14 -> 29 -> 14 -> 3 -> 37
(2)
10 -> 14 -> 29 -> 14 -> 3 -> 37
10 -> 14 -> 29 -> 14 -> 3 -> 37
10 -> 14 -> 14 -> 29 -> 3 -> 37
10 -> 14 -> 14 -> 3 -> 29 -> 37
(3)
10 -> 14 -> 14 -> 3 -> 29 -> 37
10 -> 14 -> 14 -> 3 -> 29 -> 37
10 -> 14 -> 3 -> 14 -> 29 -> 37
(4)
10 -> 14 -> 3 -> 14 -> 29 -> 37
10 -> 3 -> 14 -> 14 -> 29 -> 37
(5)
3 -> 10 -> 14 -> 14 -> 29 -> 37

分步骤写法;

这里分步骤展示排序过程

public class BubbleSortTest2 {
    public static void main(String[] args) {
        //需要排序的数组
        int[] array = {29,10,14,37,14,3};

        //临时变量,用于前后交换时临时存储;
        int temp = 0;

        //1.第一次排序;
        for (int i = 0; i < array.length - 1; i++) {
            if(array[i] > array[i+1]){
                temp = array[i];
                array[i] = array[i+1];
                array[i+1] =temp;
            }
        }

        System.out.println("第一次排序后-->"+ Arrays.toString(array));
        //第一次排序后-->[10, 14, 29, 14, 3, 37]

        //2.第二次排序;
        for (int i = 0; i < array.length - 1 - 1; i++) {
            if(array[i] > array[i+1]){
                temp = array[i];
                array[i] = array[i+1];
                array[i+1] =temp;
            }
        }

        System.out.println("第二次排序后-->"+ Arrays.toString(array));
        //第二次排序后-->[10, 14, 14, 3, 29, 37]

        //3.第三次排序
        for (int i = 0; i < array.length - 1 - 1 - 1; i++) {
            if(array[i] > array[i+1]){
                temp = array[i];
                array[i] = array[i+1];
                array[i+1] =temp;
            }
        }

        System.out.println("第三次排序后-->"+ Arrays.toString(array));
        //第三次排序后-->[10, 14, 3, 14, 29, 37]

        //4.第四次排序;
        for (int i = 0; i < array.length - 1 - 1 -1; i++) {
            if(array[i] > array[i+1]){
                temp = array[i];
                array[i] = array[i+1];
                array[i+1] =temp;
            }
        }

        System.out.println("第四次排序后-->"+ Arrays.toString(array));
        //第四次排序后-->[10, 3, 14, 14, 29, 37]

        //5.第五次排序;
        for (int i = 0; i < array.length - 1 - 1 -1; i++) {
            if(array[i] > array[i+1]){
                temp = array[i];
                array[i] = array[i+1];
                array[i+1] =temp;
            }
        }

        System.out.println("第五次排序后-->"+ Arrays.toString(array));
        //第五次排序后-->[3, 10, 14, 14, 29, 37]
    }
}

综合写法

public class BubbleSortTest {
    public static void main(String[] args) {
        //需要排序的数组
        int[] array = {29,10,14,37,14,3};
        //调用方法; 完成由大到小排序
        int[] sortArray = BubbleSort(array);
        System.out.println("冒泡排序结果-->"+Arrays.toString(sortArray));
        //冒泡排序结果-->[3, 10, 14, 14, 29, 37]
    }

    public static int[] BubbleSort(int[] array){
        for (int i = 0; i <array.length -1; i++) {
            for (int j = 0; j < array.length - i - 1; j++) {
                //后一个和之前的交换;
                if(array[j] > array[j+1]){
                    int temp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = temp;
                }
            }
            System.out.println("第"+(i+1)+"次排序后-->"+Arrays.toString(array));
        }

        return array;
    }
}

运行结果

1次排序后-->[10, 14, 29, 14, 3, 37]2次排序后-->[10, 14, 14, 3, 29, 37]3次排序后-->[10, 14, 3, 14, 29, 37]4次排序后-->[10, 3, 14, 14, 29, 37]5次排序后-->[3, 10, 14, 14, 29, 37]
冒泡排序结果-->[3, 10, 14, 14, 29, 37]

稍微优化一下

如果说,我这个数组比较特殊;
例如:3,2,14,37,14,3
看看它的执行步骤;会发现其实第三次它就排序完成了;但还进行了后面的无意义排序;

1次排序后-->[2, 3, 14, 14, 3, 37]2次排序后-->[2, 3, 14, 3, 14, 37]3次排序后-->[2, 3, 3, 14, 14, 37]4次排序后-->[2, 3, 3, 14, 14, 37]5次排序后-->[2, 3, 3, 14, 14, 37]
冒泡排序结果-->[2, 3, 3, 14, 14, 37]

那么,就对之前的冒泡排序优化一下;
在执行时加入标志位的判断;

public class BubbleSortTest3 {
    public static void main(String[] args) {
        //需要排序的数组
        int[] array = {3,2,14,37,14,3};
        //调用方法; 完成由大到小排序
        int[] sortArray = BubbleSort(array);
        System.out.println("冒泡排序结果-->"+Arrays.toString(sortArray));
    }

    public static int[] BubbleSort(int[] array){
        //定义标志位;
        boolean flag =false;
        for (int i = 0; i <array.length -1; i++) {
            for (int j = 0; j < array.length - i - 1; j++) {
                //后一个和之前的交换;
                if(array[j] > array[j+1]){
                    flag = true;
                    int temp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = temp;
                }
            }
            //对标志位判断后再决定是否继续循环;
            if(flag){
                //重置标志位;
                flag = false;
            }else {
                //表示没发生交换;跳过本次循环;
                break;
            }
            System.out.println("第"+(i+1)+"次排序后-->"+Arrays.toString(array));
        }

        return array;
    }
}

看看执行过程

1次排序后-->[2, 3, 14, 14, 3, 37]2次排序后-->[2, 3, 14, 3, 14, 37]3次排序后-->[2, 3, 3, 14, 14, 37]
冒泡排序结果-->[2, 3, 3, 14, 14, 37]

3.简单选择排序

比如说要定义由小到大的排序;
首先假设数组的第一个数是最小的数;去依次和后面的数进行比较,直到找到一个比它小的,然后将那个数标记为最小的数,接着继续依次比较;直到数组遍历结束;将带有标记的最小数字和第一个数交换;
这时,第一个数的位置就定下来了;接着开始假设第二个数为最小的数,重复之前的步骤…直到完成排序;

就用案例
8 -> 3 -> 2 -> 1 -> 7 -> 4 -> 6 -> 5来看了

图示过程–>

在这里插入图片描述

这七次排序的分解过程;

初始 =====>8 -> 3 -> 2 -> 1 -> 7 -> 4 -> 6 -> 5
(1)
1 -> 3 -> 2 -> 8 -> 7 -> 4 -> 6 -> 5
(2)
1 -> 2 -> 3 -> 8 -> 7 -> 4 -> 6 -> 5
(3)
1 -> 2 -> 3 -> 8 -> 7 -> 4 -> 6 -> 5
(4)
1 -> 2 -> 3 -> 4 -> 7 -> 8 -> 6 -> 5
(5)
1 -> 2 -> 3 -> 4 -> 5 -> 8 -> 6 -> 7
(6)
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 8 -> 7
(7)
1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8

首先是分步骤实现的方式

public class SelectSortTest {
    public static void main(String[] args) {
        //需要排序的数组;
        int[] array = {8, 3, 2, 1, 7, 4, 6, 5};
        System.out.println("选择排序之前-->   "+Arrays.toString(array));

        //--------------------- ( 1 )----------------------------------------
        //定义最小值的索引,以及最小值;
        int minIndex = 0;
        int minVal = array[0];
        //1.第一次排序;
        for (int i = 0+1; i < array.length ; i++) {
            //若比较,找到比这个最小值还小的数;就把那个数标记为最小值;
            if(minVal > array[i]){
                minIndex = i;
                minVal =array[i];
            }
        }
        //结束后,再交换;
        array[minIndex] = array[0];
        array[0] = minVal;
        System.out.println("第一次排序结束后-->"+Arrays.toString(array));

        //-----------------------( 2 )--------------------------------------
        //最小值以及索引重置;
        minIndex = 1;
        minVal = array[1];
        //2.第二次排序;
        for (int i = 1+1; i < array.length ; i++) {
            //若比较,找到比这个最小值还小的数;就把那个数标记为最小值;
            if(minVal > array[i]){
                minIndex = i;
                minVal =array[i];
            }
        }
        //结束后,再交换;
        array[minIndex] = array[1];
        array[1] = minVal;
        System.out.println("第二次排序结束后-->"+Arrays.toString(array));

        //------------------------( 3 )-------------------------------------
        //最小值以及索引重置;
        minIndex = 2;
        minVal = array[2];
        //3.第三次排序;
        for (int i = 1+1+1; i < array.length ; i++) {
            //若比较,找到比这个最小值还小的数;就把那个数标记为最小值;
            if(minVal > array[i]){
                minIndex = i;
                minVal =array[i];
            }
        }
        //结束后,再交换;
        array[minIndex] = array[2];
        array[2] = minVal;
        System.out.println("第三次排序结束后-->"+Arrays.toString(array));

        //------------------------( 4 )-------------------------------------
        //最小值以及索引重置;
        minIndex = 3;
        minVal = array[3];
        //4.第四次排序;
        for (int i = 1+1+1+1; i < array.length ; i++) {
            //若比较,找到比这个最小值还小的数;就把那个数标记为最小值;
            if(minVal > array[i]){
                minIndex = i;
                minVal =array[i];
            }
        }
        //结束后,再交换;
        array[minIndex] = array[3];
        array[3] = minVal;
        System.out.println("第四次排序结束后-->"+Arrays.toString(array));

        //-------------------------( 5 )------------------------------------
        //最小值以及索引重置;
        minIndex = 4;
        minVal = array[4];
        //5.第五次排序;
        for (int i = 1+1+1+1+1; i < array.length ; i++) {
            //若比较,找到比这个最小值还小的数;就把那个数标记为最小值;
            if(minVal > array[i]){
                minIndex = i;
                minVal =array[i];
            }
        }
        //结束后,再交换;
        array[minIndex] = array[4];
        array[4] = minVal;
        System.out.println("第五次排序结束后-->"+Arrays.toString(array));

        //--------------------------( 6 )-----------------------------------
        //最小值以及索引重置;
        minIndex = 5;
        minVal = array[5];
        //6.第六次排序;
        for (int i = 1+1+1+1+1+1; i < array.length ; i++) {
            //若比较,找到比这个最小值还小的数;就把那个数标记为最小值;
            if(minVal > array[i]){
                minIndex = i;
                minVal =array[i];
            }
        }
        //结束后,再交换;
        array[minIndex] = array[5];
        array[5] = minVal;
        System.out.println("第六次排序结束后-->"+Arrays.toString(array));

        //---------------------------( 7 )----------------------------------
        //最小值以及索引重置;
        minIndex = 6;
        minVal = array[6];
        //7.第七次排序;
        for (int i = 1+1+1+1+1+1+1; i < array.length ; i++) {
            //若比较,找到比这个最小值还小的数;就把那个数标记为最小值;
            if(minVal > array[i]){
                minIndex = i;
                minVal =array[i];
            }
        }
        //结束后,再交换;
        array[minIndex] = array[6];
        array[6] = minVal;
        System.out.println("第七次排序结束后-->"+Arrays.toString(array));
    }
}

结果过程

选择排序之前-->   [8, 3, 2, 1, 7, 4, 6, 5]
第一次排序结束后-->[1, 3, 2, 8, 7, 4, 6, 5]
第二次排序结束后-->[1, 2, 3, 8, 7, 4, 6, 5]
第三次排序结束后-->[1, 2, 3, 8, 7, 4, 6, 5]
第四次排序结束后-->[1, 2, 3, 4, 7, 8, 6, 5]
第五次排序结束后-->[1, 2, 3, 4, 5, 8, 6, 7]
第六次排序结束后-->[1, 2, 3, 4, 5, 6, 8, 7]
第七次排序结束后-->[1, 2, 3, 4, 5, 6, 7, 8]

稍微优化一下

public class SelectSortTest01 {
    public static void main(String[] args) {
        //需要排序的数组;
        int[] array = {8, 3, 2, 1, 7, 4, 6, 5};
        int[] result = SelectSort(array);
        System.out.println("选择排序结束后的-->"+Arrays.toString(result));
        //选择排序结束后的-->[1, 2, 3, 4, 5, 6, 7, 8]
    }

    //选择排序的方法;
    public static int[] SelectSort(int[] array) {
        for (int i = 0; i < array.length - 1; i++) {
            //定义最小值的索引,最小值; 先假设当前的数为最小的;
            int minIndex = i;
            int minVal = array[i];
            for (int j = i + 1; j < array.length; j++) {
                //比较最小值和其他的数;
                if (minVal > array[j]) {
                    //仅标记最小值,以及得到它的索引;
                    minVal = array[j];
                    minIndex = j;
                }
            }
            //若最小值不是假设的那个;
            if (minIndex != i) {
                //交换最小值;
                array[minIndex] = array[i];
                array[i] = minVal;
            }
        }
        return array;
    }
}

4.直接插入排序

首先假设第一个元素是已经排序好的有序表,后面的元素都是无序的;
然后从第二个元素开始; 和前面的第一个有序表元素比较,放入合适的位置;
然后这时前两个元素形成有序表,后面的是无序的;
然后这时把第三个元素获取到,和前面的有序表(已经有两个元素了)比较;放入合适的位置;
… 以此类推;直到将所有的元素排序完毕.

例如;要对16 - >3 -> 12 -> 1 -> 30 -> 6 进行插入排序
图解–>

在这里插入图片描述

  • 首先明确,待插入的数是从第2个数开始的;也就是数组下标索引 为 1的数;
  • 那么,先把待插入的数值存起来;然后他要插入,首先找的是前面有序表的最后一个;也就是这个待插入数值的下标的前一个;
  • 若这个待插入的数值比前面的有序表最后一个数还大,那么直接把它放在有序表的最后一个位置;
  • 然后,它如果比前面的有序表最后一个还小,就说明它要放入前面的表里面;那么首先让前面的挪一个位置出来,放到这个待插入的数的原来位置;
  • 注意这个待插入数的值已经提前被取出来了,那么它在有序表中找位置,还是一样的,和前面的比较;…
  • 直到找到最前面的一个,一定注意不能数组越界

首先还是分步骤的实现

package day06sorting.sort03_insertionsort;

import java.util.Arrays;
/**
 * @author by CSDN@小智RE0
 * @date 2021-11-04 21:18
 * 插入排序,分步骤 写一下
 */
public class InsertionSortTest {
    public static void main(String[] args) {
        //需要完成排序的数组;
        int[] array = {16,3,12,1,30,6};
        System.out.println("排序之前的数组-->"+ Arrays.toString(array));

        //---------------------( 1 )-------------------------------->
        //首先定义待插入的元素; 以及它的(前一个位置)待插入点;  注意第一步从第二个元素开始;
        int insertVal = array[1];
        int insertIndex = 1 - 1 ;
        //判断是否可插入前面 有序表 的条件;
        while (insertIndex >=0 && array[insertIndex] > insertVal){
            //将它的前一个数换到后面来;腾出位置;
            array[insertIndex +1 ] = array[insertIndex];
            //待插入点前移;
            insertIndex -- ;
        }
        //注意,上面可能会让 insertIndex 待插入点到达 -1 位置;
        //这里把这个确定的最小值放入插入点;
        array[insertIndex +1 ] = insertVal;
        System.out.println("第一次插入排序后-->"+Arrays.toString(array));

        //---------------------( 2 )-------------------------------->
        //改变待插入的元素 以及 待插入点
        insertVal = array[2];
        insertIndex = 2 - 1 ;
        //判断是否可插入前面 有序表 的条件;
        while (insertIndex >=0 && array[insertIndex] > insertVal){
            //将它的前一个数换到后面来;腾出位置;
            array[insertIndex +1 ] = array[insertIndex];
            //待插入点前移;
            insertIndex -- ;
        }
        //注意,上面可能会让 insertIndex 待插入点到达 -1 位置;
        //这里把这个确定的最小值放入插入点;
        array[insertIndex +1 ] = insertVal;
        System.out.println("第二次插入排序后-->"+Arrays.toString(array));

        //---------------------( 3 )-------------------------------->
        //改变待插入的元素 以及 待插入点
        insertVal = array[3];
        insertIndex = 3 - 1 ;
        //判断是否可插入前面 有序表 的条件;
        while (insertIndex >=0 && array[insertIndex] > insertVal){
            //将它的前一个数换到后面来;腾出位置;
            array[insertIndex +1 ] = array[insertIndex];
            //待插入点前移;
            insertIndex -- ;
        }
        //注意,上面可能会让 insertIndex 待插入点到达 -1 位置;
        //这里把这个确定的最小值放入插入点;
        array[insertIndex +1 ] = insertVal;
        System.out.println("第三次插入排序后-->"+Arrays.toString(array));

        //---------------------( 4 )-------------------------------->
        //改变待插入的元素 以及 待插入点
        insertVal = array[4];
        insertIndex = 4 - 1 ;
        //判断是否可插入前面 有序表 的条件;
        while (insertIndex >=0 && array[insertIndex] > insertVal){
            //将它的前一个数换到后面来;腾出位置;
            array[insertIndex +1 ] = array[insertIndex];
            //待插入点前移;
            insertIndex -- ;
        }
        //注意,上面可能会让 insertIndex 待插入点到达 -1 位置;
        //这里把这个确定的最小值放入插入点;
        array[insertIndex +1 ] = insertVal;
        System.out.println("第四次插入排序后-->"+Arrays.toString(array));

        //---------------------( 5 )-------------------------------->
        //改变待插入的元素 以及 待插入点
        insertVal = array[5];
        insertIndex = 5 - 1 ;
        //判断是否可插入前面 有序表 的条件;
        while (insertIndex >=0 && array[insertIndex] > insertVal){
            //将它的前一个数换到后面来;腾出位置;
            array[insertIndex +1 ] = array[insertIndex];
            //待插入点前移;
            insertIndex -- ;
        }
        //注意,上面可能会让 insertIndex 待插入点到达 -1 位置;
        //将待插入元素放到那个合适的位置; 注意上面的值由于在循环内要进行 -- 运算,然后才在条件判断;所以实际的待插入点在后一位;
        array[insertIndex +1 ] = insertVal;
        System.out.println("第五次插入排序后-->"+Arrays.toString(array));
    }
}

结果

排序之前的数组-->[16, 3, 12, 1, 30, 6]
第一次插入排序后-->[3, 16, 12, 1, 30, 6]
第二次插入排序后-->[3, 12, 16, 1, 30, 6]
第三次插入排序后-->[1, 3, 12, 16, 30, 6]
第四次插入排序后-->[1, 3, 12, 16, 30, 6]
第五次插入排序后-->[1, 3, 6, 12, 16, 30]

稍微优化一下

package day06sorting.sort03_insertionsort;

import java.util.Arrays;

/**
 * @author by CSDN@小智RE0
 * @date 2021-11-04 21:44
 * 插入排序
 */
public class InsertionSortTest02 {
    public static void main(String[] args) {
        //定义要排序的数组;
        int[] array ={16,3,12,1,30,6};
        System.out.println("排序之前的数组-->"+ Arrays.toString(array));
        //进行插入排序;
        int[] sort = InsertionSort(array);
        System.out.println("排序结束后的数组-->"+Arrays.toString(array));
    }

    //插入排序方法;
    public static int[]  InsertionSort(int[] array){
        //首先明白,待插入的元素是从第二个元素开始的,所以它遍历的长度自然就是数组的长度了;
        for (int i = 1; i < array.length ; i++) {
            //待插入的元素,待插入的位置;
            int insertVal = array[i];
            int insertIndex = i -1;
            //遍历前面的有序表;找找合适的位置;
            while (insertIndex >= 0 && array[insertIndex] > insertVal){
                //前面的一个元素换到后面;
                array[insertIndex+1] = array[insertIndex];
                //待插入点前移;
                insertIndex -- ;
            }
            //将待插入元素放到那个合适的位置; 注意上面的值由于在循环内要进行 -- 运算,然后才在条件判断;所以实际的待插入点在后一位;
            array[insertIndex+1] =insertVal;

            System.out.println("第"+i+"次插入排序==>"+Arrays.toString(array));
        }
        return array;
    }
}

结果

排序之前的数组-->[16, 3, 12, 1, 30, 6]1次插入排序==>[3, 16, 12, 1, 30, 6]2次插入排序==>[3, 12, 16, 1, 30, 6]3次插入排序==>[1, 3, 12, 16, 30, 6]4次插入排序==>[1, 3, 12, 16, 30, 6]5次插入排序==>[1, 3, 6, 12, 16, 30]
排序结束后的数组-->[1, 3, 6, 12, 16, 30]

5. 希尔排序

在刚才的排序中,可以看到一个比较麻烦的状况;
如果说待插入的这个数啊,它就是比前面假设的有序表里面的元素都小,那么它想到达这有序表合适的位置,就得让这有序表的元素一个个地后移,这要是数据量大的话,也会浪费时间;

那么希尔排序就优化了插入排序的过程;缩小增量;对数组不断地分组,直到增量缩小到1;

图示

在这里插入图片描述

在这里插入图片描述

交换式 实现

分步骤实现

public class SheelSortTest {
    public static void main(String[] args) {
        int[] array ={8,9,1,7,2,3,5,4,6,0};
        //首先是分步骤实现;
        System.out.println("排序前的数组-->"+ Arrays.toString(array));

        //定义临时变量;
        int temp =0;

        //1.首先两两一组,分为5组; 步长为5;
        for (int i = 5; i < array.length; i++) {
            for (int j = i -5; j >=0 ; j-=5) {
                //交换;
                if(array[j]>array[j+5]){
                    temp = array[j];
                    array[j] = array[j+5];
                    array[j+5] = temp;
                }
            }
        }
        System.out.println("第一次排序--->"+ Arrays.toString(array));

        //2.交换后,分为2组; 步长为2;
        for (int i = 2; i < array.length; i++) {
            for (int j = i -2; j >=0 ; j-=2) {
                //交换;
                if(array[j]>array[j+2]){
                    temp = array[j];
                    array[j] = array[j+2];
                    array[j+2] = temp;
                }
            }
        }
        System.out.println("第二次排序--->"+ Arrays.toString(array));

        //3.分为1组; 步长为1;
        for (int i = 1; i < array.length; i++) {
            for (int j = i -1; j >=0 ; j-=1) {
                //交换;
                if(array[j]>array[j+1]){
                    temp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = temp;
                }
            }
        }
        System.out.println("第三次排序--->"+ Arrays.toString(array));
    }
}
排序前的数组-->[8, 9, 1, 7, 2, 3, 5, 4, 6, 0]
第一次排序--->[3, 5, 1, 6, 0, 8, 9, 4, 7, 2]
第二次排序--->[0, 2, 1, 4, 3, 5, 7, 6, 9, 8]
第三次排序--->[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

综合一下

public class SheelSortTest01 {
    public static void main(String[] args) {
        //需要排序的数组;
        int[] array ={15,25,1,6,8,2,99,27,36,0,55};
        System.out.println("排序前的数组->"+Arrays.toString(array));
        int[] sheelSortExchange = sheelSortExchange(array);
        System.out.println("排序后的数组->"+Arrays.toString(sheelSortExchange));
    }

    //交换式希尔排序
    public static  int[] sheelSortExchange(int[] array){
        //定义变量记录排序的次数;
        int num =0;
        //每次按一半进行分组;
        for (int group = array.length/2; group >0 ; group/=2) {
            //分组;
            for (int i = group; i < array.length; i++) {
                //组内交换;
                for (int j = i - group; j >=0 ; j-=group) {
                    //由小到大交换;
                    if(array[j]>array[j+group]){
                        int temp = array[j];
                        array[j] = array[j+group];
                        array[j+group] = temp;
                    }
                }
            }
            System.out.println("第"+(++num)+"次排序后-->"+ Arrays.toString(array));
        }
        return array;
    }
}

排序结果

排序前的数组->[15, 25, 1, 6, 8, 2, 99, 27, 36, 0, 55]1次排序后-->[2, 25, 1, 6, 0, 15, 99, 27, 36, 8, 55]2次排序后-->[0, 6, 1, 8, 2, 15, 36, 25, 55, 27, 99]3次排序后-->[0, 1, 2, 6, 8, 15, 25, 27, 36, 55, 99]
排序后的数组->[0, 1, 2, 6, 8, 15, 25, 27, 36, 55, 99]

移位方式 实现

public class SheelSortTest02 {
    public static void main(String[] args) {

        //需要排序的数组;
        int[] array ={18,99,0,6,25,36,15,4,2,1,15};
        System.out.println("排序前的数组-->"+Arrays.toString(array));
        int[] sortShift = sheelSortShift(array);
        System.out.println("排序后的数组-->"+Arrays.toString(sortShift));
    }

    //移位式希尔排序;
    public static int[] sheelSortShift(int[] array){
        //定义变量为排序计数;
        int num = 0 ;
        //先保障缩小增量;
        for (int group = array.length/2; group >0 ; group/=2) {
            //移动位置;
            for (int i = group; i < array.length ; i++) {
                //组内插入前先保存待插入的点位和数值;
                int insertIndex = i;
                int insertVal = array[i];
                //若这个待插入数比它同组的前面那个数还小,就考虑移动位置插入;
                if(array[insertIndex] < array[insertIndex - group]){
                    //不断遍历,直至找到合适位置
                    while (insertIndex -group >= 0 && insertVal < array[insertIndex -group]){
                        //将组内前面的位置空出来;
                        array[insertIndex] =  array[insertIndex - group];
                        //移动要插入的位置;
                        insertIndex -= group;
                    }
                    //将待插入点放到合适位置;
                    array[insertIndex] = insertVal;
                }
            }
            System.out.println("第"+(++num)+"次排序后-->"+Arrays.toString(array));
        }
        return array;
    }
}

排序后结果

排序前的数组-->[18, 99, 0, 6, 25, 36, 15, 4, 2, 1, 15]1次排序后-->[15, 15, 0, 2, 1, 18, 99, 4, 6, 25, 36]2次排序后-->[0, 2, 1, 4, 6, 15, 15, 18, 36, 25, 99]3次排序后-->[0, 1, 2, 4, 6, 15, 15, 18, 25, 36, 99]
排序后的数组-->[0, 1, 2, 4, 6, 15, 15, 18, 25, 36, 99]

6.快速排序

通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分
的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序

例如对数组40,2,22,25,14,1,3进行排序

在这里插入图片描述

图解案例1;

在这里插入图片描述

图解案例2对 [-9,78,0,23,-567,70] 进行从小到大的排序

在这里插入图片描述

实现完成

public class QuickSortTest {
    public static void main(String[] args) {
        //需要排序的数组;
        int[] array ={40,2,22,25,14,1,3};

        int[] quickSort = quickSort(array, 0, array.length - 1);
        System.out.println(Arrays.toString(quickSort));
    }

    /**
     * 快速排序
     * @param array 需要排序的数组
     * @param left  左指针
     * @param right 右指针
     * @return      排序后的数组
     */
    public static int[] quickSort(int[] array,int left,int right){
        //先把左右指针提前存起来;
        int l = left;
        int r = right;
        //找到中心点;
        int bottom = array[(left +right)/2];
        System.out.println("当前中心轴值-->"+bottom);
        //左指针 和 右指针向中心移动;
        while (l < r){
            //左右指针移动;
            while (array[l] < bottom){
                l+=1;
            }
            while (array[r] > bottom){
                r-=1;
            }

            //跳出循环的条件;
            if(l>=r){
                break;
            }
            //先进行交换;
            int temp =array[l];
            array[l] = array[r];
            array[r] = temp;

            //考虑接近到达中心点的情况;
            if(array[l] == bottom){
                r-=1;
            }
            if(array[r] == bottom){
                l+=1;
            }
        }

        //还需考虑两指针相遇的情况;
        if(l == r){
            l+=1;
            r-=1;
        }

        //向左递归;
        if(left<r){
            quickSort(array,left,r);
        }

        //向右递归;
        if(right>l){
            quickSort(array,l,right);
        }

        return array;
    }
}

执行过程

当前中心轴值-->25
当前中心轴值-->22
当前中心轴值-->2
当前中心轴值-->14
[1, 2, 3, 14, 22, 25, 40]

7.归并排序

该算法使用到了分治(分而治之)算法的思想,将大的问题细分为小的问题进行处理

例如图解数组[ 8 , 4 , 5 , 7, 1, 3, 6, 2 ]过程

在这里插入图片描述

最后一个治理合并为有序数组的过程

在这里插入图片描述

在这里插入图片描述

图示对12,3,8,20,18,1,5进行排序

在这里插入图片描述

具体的实现过程

package day06sorting.sort06_mergesort;

import java.util.Arrays;

/**
 * @author by CSDN@小智RE0
 * @date 2021-11-06 13:48
 * 归并排序
 */
public class MergeSortTest {
    public static void main(String[] args) {
        //需要排序的数组;
        int[] array= {12,3,8,20,18,1,5};
        //临时数组;
        int[] temp = new int[array.length];
        //归并排序;
        mergeSort(array,0, array.length - 1,temp );
        System.out.println(Arrays.toString(array));
    }


    /**
     * 分化数组
     * @param array 原数组
     * @param left  左索引
     * @param right 右索引
     * @param temp  临时数组
     */
    public static void mergeSort(int[] array, int left, int right, int[] temp){
        if(left < right){
            //直接定义中心索引;
            int middle = (left + right) / 2;
            //左边递归分化;
            mergeSort(array,left,middle,temp);
            //右边递归分化;
            mergeSort(array,middle+1,right,temp);
            //合并数组;
            mergeArray(array,left,right,middle,temp);
        }
    }


    /**
     * 首先从合并处理开始写;
     * @param array 原数组
     * @param left  左边的数组索引
     * @param right 右边的数组索引
     * @param middle 中间的索引
     * @param tempArray 临时的数组
     */
    private static void mergeArray(int[] array, int left, int right, int middle, int[] tempArray){
        //先确定i作为左边的索引;j作为右边列表的索引;
        int i = left;
        int j = middle + 1;
        //临时数组的索引;
        int tempIndex = 0;

        //首先根据需要,由小到大把一块数组先放入临时数组;
        while (i <= middle && j<=right){
            //左边的放入临时数组;
            if(array[i] <= array[j]){
                tempArray[tempIndex] = array[i];
                i+=1;
                tempIndex+=1;
            }else {
               //否则右边的放入临时数组;
                tempArray[tempIndex] = array[j];
                j+=1;
                tempIndex+=1;
            }
        }

        //可能一块的数组已经存完了,但是另一块还有剩余,那就全部存入临时数组;
        while (i<= middle){
            tempArray[tempIndex] = array[i];
            i+=1;
            tempIndex+=1;
        }
        while (j<=right){
            tempArray[tempIndex] = array[j];
            j+=1;
            tempIndex+=1;
        }

        //最终要把临时数组的放进原数组中去;
        //但是注意,由于要递归,这边的拷贝索引是动态的;
        //这里先初始化临时的索引;
        tempIndex = 0;
        //定义拷贝时的原数组左边动态索引;
        int originalLeftIndex = left;

        System.out.println("此时左索引originalLeftIndex==>"+originalLeftIndex +"此时右索引right==>"+right);
        while (originalLeftIndex<=right){
            array[originalLeftIndex] = tempArray[tempIndex];
            originalLeftIndex+=1;
            tempIndex+=1;
        }

    }

}

执行结果

此时左索引originalLeftIndex==>0此时右索引right==>1
此时左索引originalLeftIndex==>2此时右索引right==>3
此时左索引originalLeftIndex==>0此时右索引right==>3
此时左索引originalLeftIndex==>4此时右索引right==>5
此时左索引originalLeftIndex==>4此时右索引right==>6
此时左索引originalLeftIndex==>0此时右索引right==>6
[1, 3, 5, 8, 12, 18, 20]

8.基数排序

将所有待比较数值统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。
以空间换时间;若数据量过大,会出现内存问题(OOM).

图示 数组[ 53, 3, 542, 748, 14, 214 ]的排序过程

在这里插入图片描述

图解过程

(1)
在这里插入图片描述

(2)

若这个元素没有十位数的话就补零,放在第一个桶里(即下标为0的那个数组),

在这里插入图片描述

(3)

同理,若没有百位数也在前面补零,放在第一个桶里

在这里插入图片描述

在实现时,用二维数组表示这10个桶数组;
每个桶的大小就设置为最大的,也就是需要排序的数组长度;
然后,还需要考虑每个桶实际存入的元素个数,以便于取出时可以明确地知道是否要遍历,遍历几次;

首先是分步骤完成

package day06sorting.sort07_basesort;

import java.util.Arrays;

/**
 * @author by CSDN@小智RE0
 * @date 2021-11-06 16:12
 * 基数排序
 */
public class BaseSortTest {
    public static void main(String[] args) {

        //需要排序的数组;
        int[] array ={53,77,3,542,748,14,214};

        //分步骤完成过程;

        //定义二维数组方放10个桶;
        int[][] barrel = new int[10][array.length];

        //定义数组记录桶中元素的个数;
        int[] barrelCount =new int[10];

        //取出元素时,原数组的索引;
        int index = 0 ;

        System.out.println("第一次排序---->");
        //向桶里放入数据;
        for (int value : array) {
            //第一次是取个位数的;
            int numberOrders = value % 10;
            barrel[numberOrders][barrelCount[numberOrders]] = value;
            //注意要计数;
            barrelCount[numberOrders]++;
        }
        //把桶里的数又按顺序拿出来放进数组;
        for (int i = 0; i < barrelCount.length; i++) {
            //首先保证桶里有没有数据;
            if(barrelCount[i]!=0){
                for (int j = 0; j < barrelCount[i]; j++) {
                    array[index++] = barrel[i][j];
                }
            }
        }
        System.out.println("第一次排序后-->"+ Arrays.toString(array));


        System.out.println("第二次排序---->");
        //需要重置计数的数组;
        barrelCount =new int[10];
        //向桶里放入数据;
        for (int k : array) {
            //第一次是取个位数的;
            int numberOrders = k / 10 % 10;
            barrel[numberOrders][barrelCount[numberOrders]] = k;
            //注意要计数;
            barrelCount[numberOrders]++;
        }
        //注意index要重置;
        index =0;

        //把桶里的数又按顺序拿出来放进数组;
        for (int i = 0; i < barrelCount.length; i++) {
            //首先保证桶里有没有数据;
            if(barrelCount[i]!=0){
                for (int j = 0; j < barrelCount[i]; j++) {
                    array[index++] = barrel[i][j];
                }
            }
        }
        System.out.println("第二次排序后-->"+ Arrays.toString(array));

        System.out.println("第三次排序---->");
        //需要重置计数的数组;
        barrelCount =new int[10];
        //向桶里放入数据;
        for (int k : array) {
            //第一次是取个位数的;
            int numberOrders = k / 10 / 10 % 10;
            barrel[numberOrders][barrelCount[numberOrders]] = k;
            //注意要计数;
            barrelCount[numberOrders]++;
        }
        //注意index要重置;
        index =0;

        //把桶里的数又按顺序拿出来放进数组;
        for (int i = 0; i < barrelCount.length; i++) {
            //首先保证桶里有没有数据;
            if(barrelCount[i]!=0){
                for (int j = 0; j < barrelCount[i]; j++) {
                    array[index++] = barrel[i][j];
                }
            }
        }
        System.out.println("第三次排序后-->"+ Arrays.toString(array));
    }
}

执行的过程

第一次排序---->
第一次排序后-->[542, 53, 3, 14, 214, 77, 748]
第二次排序---->
第二次排序后-->[3, 14, 214, 542, 748, 53, 77]
第三次排序---->
第三次排序后-->[3, 14, 53, 77, 214, 542, 748]

稍微优化一下

将这个分步的写法综合一下,因为实际计算时并不是说固定的排序几次;
首先就得找出最大值的长度;以便于确定要去排序几次;

//基数排序的方式;
public static void baseSort(int[] array) {
    int maxVal = array[0];
    //首先找最大值,
    for (int j : array) {
        if (j >= maxVal) {
            maxVal = j;
        }
    }
    //得到最大值的长度;
    int maxLength = (maxVal + "").length();
    //输出测试一下;
    System.out.println("当前要排序数组的最大元素为:" + maxVal + " 最大长度为:" + maxLength);

    //定义二维数组放置10个桶;
    int[][] barrel = new int[10][array.length];
    //定义一个数组来记录每个桶的元素数量;
    int[] barrelCount = new int[10];

    for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {
        for (int value : array) {
            //第一次取个位数;第二次取十位数;以此列推;
            int numberOrders = value / n % 10;
            //存入桶中;
            barrel[numberOrders][barrelCount[numberOrders]] = value;
            //计数递增;
            barrelCount[numberOrders]++;
        }

        //数组的索引;
        int index = 0;
        //取出桶的元素存向数组;
        for (int k = 0; k < barrelCount.length; k++) {
            //先判断桶里有没有元素;
            if (barrelCount[k] != 0) {
                for (int j = 0; j < barrelCount[k]; j++) {
                    array[index++] = barrel[k][j];
                }
            }
            //重置记录桶的元素数量的数组;
            barrelCount[k] = 0;
        }
    }
}

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


2021年 11 月 16 日添加堆排序

9. 堆排序

9.1 关于堆的几个基础知识

学习堆排序之前,当然要先去了解什么是大顶堆,什么是小顶堆

堆是具有优先级性质的完全二叉树
在之后的这篇文章;主要针对于自定义大顶堆;其中也涉及到了堆排序的方法;
文章链接地址---->数据结构(六) —[实现 堆(heap)(包含方法图解过程) 优先队列(Priority Queue)]

其实,规定一下,数字值越大优先级越高,
大顶堆的话;就是优先级最高的是 根结点,父节点的数值永远大于或等于左右子节点的数值;
小顶堆就是;优先级最小的是 根结点 ,父节点的数值永远小于或等于左右子节点的数值;

不管是大顶堆还是小顶堆;前提都是要基于完全二叉树

下面这简易的两个堆图;大概就是这个意思
一般用大顶堆处理升序问题,用小顶堆处理降序问题;

在这里插入图片描述

在这里插入图片描述

当然,在堆中,或者说,
把一个数组放到一棵二叉树里面,
若从索引0开始;作为树的根结点;那么其实可以推导出;

  • 由于根结点没有父节点;那么除过根节点之外的节点 ;
    • 这个节点的父节点索引就是ParentIndex = [(当前结点索引-1) / 2];
  • 只要是有左右子结点的节点 ;
    • 这个结点的左结点索引就是 leftIndex = ( 2 * 当前结点索引) +1;
    • 这个结点的右结点索引就是rightIndex = ( 2 * 当前结点索引) + 2 = leftIndex +1;

在这里插入图片描述


9.2 堆排序的思想

这里的话,堆排序还是用大顶堆进行堆排序的学习

  • 首先把这个给定的数组构建成一个堆,
  • 实际上只是逻辑上构建为一个堆;本质上还是数组(怎么说呢,这个数组实际上就是二叉树层序遍历得到的数组);
  • 当然,这个得到的数组,第一个元素就是目前的最大值了;
  • 这时,让第一个元素和最后一个元素交换,(注意交换后,原先换到后面的节点就不再参与堆的操作了;)交换之后;需要对这个堆的剩余结点进行调整;这样反复操作;
  • 这样最终把这个数组操作完毕,其实得到的就是有序数组了;即完成堆排序;
图解

这里的数组转大顶堆方式还和我用的那个方法略有不同

📢(1)首先是数组转换成大顶堆

比如初始数组为 [ 6 , 8 , 2 , 10 , 13 ]

在这里插入图片描述

这里先找到最后一个非叶子节点;
那么这里也比较巧妙;这个结点的索引就是 (array.length/2) - 1 ;即(5/2)-1 = 1 ;
计算得出这个要操作的节点是索引为1 的节点 8 ;

在这里插入图片描述

然后,这个结点的具体操作是,让它和左右子节点进行比较;和数值大的进行交换;
比如我这里这个案例中;让节点8和13进行交换;

在这里插入图片描述

然后,继续操作,这里找的是第二个非叶子节点;
我这案例中,就找到了节点 6

在这里插入图片描述

对节点 6 进行操作;由于13大于6,那么交换13和6;

在这里插入图片描述

这时由于交换过来的节点 6 还具有子节点;且排序不合适,
那么比较之后,将节点 10 和节点 6 进行交换

在这里插入图片描述

到这一步,大顶堆其实已经构建成型了;

在这里插入图片描述

📢 (2)开始对大顶堆进行操作

具体操作是,每次都找堆顶的根结点和最后一个节点交换位置; 这里的换到后面的节点13已经不会再参与到后面的操作了;

例如我这个案例,就找到根结点13,和最后一个节点 8 进行交换;
在这里插入图片描述

交换后,注意到,这时剩余的节点组合可能不符合大顶堆了,那就进行调整,把它再次变为大顶堆;

我这个案例中,就把10和8 进行交换了,他现在符合大顶堆的结构
在这里插入图片描述

Ok,这时;把根结点10 和 最后一个节点 6 进行交换;

在这里插入图片描述

这时在进行调整,将6与8进行交换 ;调整为大顶堆

在这里插入图片描述

OK,把这个根结点8和最后一个节点 2 进行交换

在这里插入图片描述

交换后,进行调整,让 节点 2 和节点 6 进行交换;此时符合大顶堆结构;

在这里插入图片描述

让第一个节点 6 和最后一个节点 2 进行交换;

在这里插入图片描述

看到仅剩根节点了;那就把这个根结点也脱离原先的堆,即完成排序

在这里插入图片描述


9.3 具体实现堆排序

/**
* 堆排序  最终完成的数组为升序的;
*
* @param array 要排序的数组
*/
public static void myHeapSort(int[] array) {
   //1.这里首先把数组转为大顶堆; 注意刚开始操作的节点是第一个非叶子节点;
   for (int i = (array.length / 2) - 1; i >= 0; i--) {
       //调用转换方法;
       getMaxHeap(array, i, array.length);
   }

   int temp = 0;
   //2.然后让最后一项和根节点进行交换;
   for (int i = array.length - 1; i > 0; i--) {
       //交换;
       temp = array[0];
       array[0] = array[i];
       array[i] = temp;
       //进行调整为大顶堆;注意每次调整的数组已经不包含最后一个元素了;
       getMaxHeap(array,0,i);
   }
}


/**
* 每次调整数组转换为大顶堆的底层实现;
* 当前节点的 左节点索引就是 ( 2*当前索引 +1 ); 右结点索引就是 (2*当前索引 +2 )= 左节点+1 ;
*
* @param array  要转换的数组
* @param index  当前操作节点的索引
* @param length 数组的长度
*/
private static void getMaxHeap(int[] array, int index, int length) {
   //先把这个结点的值临时存起来;
   int tempVal = array[index];

   //向左子节点查找;每次都去找上一个操作节点的左节点;
   for (int i = index * 2 + 1; i < length; i = i * 2 + 1) {
       //若出现 右节点 大于 左节点 的情况;
       if (i + 1 < length && array[i] < array[i + 1]) {
           //这时就把和操作节点比较的权利交给 右结点;
           i++;
       }

       //若这个操作节点的值 比他下面的子节点还大,那就跳出这个循环;
       if (tempVal > array[i]) {
           break;
       } else {
           //否则就进行交换; 把这个较大的子节点放到操作节点的位置;
           array[index] = array[i];
           //这时把操作节点就是这个换过来的节点;
           index = i;
       }
   }
   //最后,在把操作的节点放到交换后的位置;
   array[index] = tempVal;
}

测试

public class MaxHeapSort {
    //测试;
    public static void main(String[] args) {
        int[] array = {6, 8, 2, 10, 13};
        System.out.println("原始数组-->"+Arrays.toString(array));
        myHeapSort(array);
        System.out.println("排序后的数组-->"+Arrays.toString(array));
    }
}    

测试结果;和分析的一致

原始数组-->[6, 8, 2, 10, 13]
排序后的数组-->[2, 6, 8, 10, 13]
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小智RE0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值