八大排序-直接插入排序、希尔排序、直接选择排序、冒泡排序、堆排序、快速排序、归并排序、基数排序(上)2

简介: 八大排序-直接插入排序、希尔排序、直接选择排序、冒泡排序、堆排序、快速排序、归并排序、基数排序(上)2

五、复杂度

不稳定,时间复杂度是O(nlogn)~O(n^2),空间复杂度是O(1)

堆排序(Heap Sort)

一、概念

1.1什么是堆

  • 分为大顶堆和小顶堆
  • 符合完全二叉树
  • 父节点大于(或小于)子节点
  • 第一个非叶子节点:n/2-1(向下取整)

二、排序思想

  1. 首先将待排序的数组构造成一个大根堆,此时,整个数组的最大值就是堆结构的顶端
  2. 将顶端的数与末尾的数交换,此时,末尾的数为最大值,剩余待排序数组个数为n-1
  3. 将剩余的n-1个数再构造成大根堆,再将顶端数与n-1位置的数交换,如此反复执行,便能得到有序数组

三、图示过程最大值和末尾的最小值交换位置 重复以上操作 四、代码

4.1代码

public class HeapSort {
    public static void heapSort(int[] arr) {
        // 构建初始大根堆
        buildMaxHeap(arr);
        // 从最后一个非叶子节点开始,依次向上调整堆
        for (int i = arr.length - 1; i > 0; i--) {
            swap(arr, 0, i); // 将堆顶元素(最大值)与最后一个元素交换
            maxHeapify(arr, 0, i); // 调整堆
        }
    }
    private static void buildMaxHeap(int[] arr) {
        // 从最后一个非叶子节点开始,依次向上调整堆
        for (int i = arr.length / 2 - 1; i >= 0; i--) {
            maxHeapify(arr, i, arr.length);
        }
    }
    private static void maxHeapify(int[] arr, int i, int heapSize) {
        int left = 2 * i + 1; // 左子节点下标
        int right = 2 * i + 2; // 右子节点下标
        int largest = i; // 最大值下标
        // 找到左、右子节点中的最大值
        if (left < heapSize && arr[left] > arr[largest]) {
            largest = left;
        }
        if (right < heapSize && arr[right] > arr[largest]) {
            largest = right;
        }
        // 如果最大值不是当前节点,交换最大值和当前节点,继续向下调整
        if (largest != i) {
            swap(arr, i, largest);
            maxHeapify(arr, largest, heapSize);
        }
    }
    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
    public static void main(String[] args) {
        int[] arr = {5, 2, 6, 0, 3, 9, 1, 7, 4, 8};
        heapSort(arr);
        for (int i : arr) {
            System.out.print(i + " ");
        }
    }
}

4.2运行结果

排序前的数组为:[5, 2, 6, 0, 3, 9, 1, 7, 4, 8]

排序后的数组为:[0, 1 ,2 ,3 ,4 ,5 ,6 ,7 ,8, 9]

4.3解释

代码中的buildMaxHeap()方法用于构建初始大根堆,maxHeapify()方法用于调整堆,heapSort()方法实现了堆排序算法。main()方法中用一个示例数组进行测试,并输出排序结果

直接选择排序(Selection Sort)

一、概念

  1. 1.选择排序是一种简单直观的排序算法
    2.无论什么数据进去都是 O(n²) 的时间复杂度。所以用到它的时候,数据规模越小越好。
  2. 3.唯一的好处可能就是不占用额外的内存空间

二、实现思路

  1. 1.首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
  2. 2.再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
  3. 3.重复第二步,直到所有元素均排序完毕。

三、图示过程四、代码

4.1代码

//Selection Sort选择排序
public class Selection {
    public static void main(String[] args) {
     int[] arr = {23,34,21,243,67,432,23,34};
        System.out.println(Arrays.toString(selection(arr)));
    }
    //选择排序
    public static int[] selection(int[] arr) {
        int temp = 0; //定义数据交换时的第三方变量
        for (int i = 0; i < arr.length - 1; i++) {
            int min = i;
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[min] > arr[j]) { //如果arr[j]的值小于arr[min]
                    min = j; //保存j的索引
                }
            }
            temp = arr[i];
            arr[i] = arr[min];
            arr[min] = temp;
            System.out.println("第" + (i + 1) + "轮插入" + Arrays.toString(arr));
        }
        return arr;
    }
}

4.2运行结果

排序前的数组为:[23,34,21,243,67,432,23,34]

排序后的数组为:[21,23,23,34,34,67,243,432]

五、代码优化

5.1代码方案一

第一种:使用一个if判断 i == arr.length-2 ,直接去掉最后一轮对比

问题,如果倒数第二轮排序 最后一位元素比倒数第二位元素小,那么去掉最后一轮排序,最终结果是没有排序完成的

//Selection Sort选择排序
public class Selection {
    public static void main(String[] args) {
     int[] arr = {23,34,21,243,67,432,23,34};
        System.out.println(Arrays.toString(selection(arr)));
    }
    //选择排序
    public static int[] selection(int[] arr) {
        int temp = 0; //定义数据交换时的第三方变量
        for (int i = 0; i < arr.length - 1; i++) {
            if( i == arr.length-2){ //如果i=数组的最后两个值
                break;  //退出循环
            }
            int min = i;
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[min] > arr[j]) { //如果arr[j]的值小于arr[min]
                    min = j; //保存j的索引
                }
            }
            temp = arr[i];
            arr[i] = arr[min];
            arr[min] = temp;
            System.out.println("第" + (i + 1) + "轮插入" + Arrays.toString(arr));
        }
        return arr;
    }
}

5.2代码方案二

第二种优化:

if(i != min ) { //判断只有在min=i时才会运行下面的代码

这种优化方法省略了很多不必要的代码运行,并优化最后一轮是否需要对比

//Selection Sort选择排序
public class Selection {
    public static void main(String[] args) {
     int[] arr = {23,34,21,243,67,432,23,34};
        System.out.println(Arrays.toString(selection(arr)));
    }
    //选择排序
    public static int[] selection(int[] arr) {
        int temp = 0; //定义数据交换时的第三方变量
        for (int i = 0; i < arr.length - 1; i++) {
            int min = i;
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[min] > arr[j]) { //如果arr[j]的值小于arr[min]
                    min = j; //保存j的索引
                }
            }
            if(i != min ) { //判断只有在min=i时才会运行下面的代码
                temp = arr[i];
                arr[i] = arr[min];
                arr[min] = temp;
                System.out.println("第" + (i + 1) + "轮插入" + Arrays.toString(arr));
            }
        }
        return arr;
    }
}

六、复杂度

是一种不稳定排序,时间复杂度是O(n^2),空间复杂度是O(1)

结构化:各个排序对比表格

133c4fbe37a144b5f26ba390d6ae28a.pngd85d5157273ab50f21d5f2df5ae61d2.png



相关文章
|
21天前
|
人工智能 算法 搜索推荐
直接插入排序、希尔排序、直接选择排序、堆排序、冒泡排序——“数据结构与算法”
直接插入排序、希尔排序、直接选择排序、堆排序、冒泡排序——“数据结构与算法”
|
1月前
|
机器学习/深度学习 搜索推荐 算法
【排序算法】插入排序与选择排序详解
【排序算法】插入排序与选择排序详解
|
10月前
|
存储 搜索推荐 算法
八大排序算法-直接插入排序、希尔排序、直接选择排序、冒泡排序、堆排序、快速排序、归并排序、基数排序(下)
八大排序算法-直接插入排序、希尔排序、直接选择排序、冒泡排序、堆排序、快速排序、归并排序、基数排序(下)
|
6月前
|
机器学习/深度学习 算法 搜索推荐
【算法】六大排序 插入排序 希尔排序 选择排序 堆排序 冒泡排序 快速排序
【算法】六大排序 插入排序 希尔排序 选择排序 堆排序 冒泡排序 快速排序
|
7月前
|
存储 搜索推荐 算法
七大排序 (9000字详解直接插入排序,希尔排序,选择排序,堆排序,冒泡排序,快速排序,归并排序)
七大排序 (9000字详解直接插入排序,希尔排序,选择排序,堆排序,冒泡排序,快速排序,归并排序)
73 0
|
7月前
|
存储 搜索推荐 算法
【算法基础】一文掌握十大排序算法,冒泡排序、插入排序、选择排序、归并排序、计数排序、基数排序、希尔排序和堆排序
【算法基础】一文掌握十大排序算法,冒泡排序、插入排序、选择排序、归并排序、计数排序、基数排序、希尔排序和堆排序
70 2
【算法基础】一文掌握十大排序算法,冒泡排序、插入排序、选择排序、归并排序、计数排序、基数排序、希尔排序和堆排序
|
10月前
|
搜索推荐 算法 Shell
八大排序-直接插入排序、希尔排序、直接选择排序、冒泡排序、堆排序、快速排序、归并排序、基数排序(上)1
八大排序-直接插入排序、希尔排序、直接选择排序、冒泡排序、堆排序、快速排序、归并排序、基数排序(上)1
|
10月前
|
搜索推荐 算法
排序算法:冒泡排序,插入排序,选择排序,归并排序,快速排序
排序算法:冒泡排序,插入排序,选择排序,归并排序,快速排序
|
11月前
|
存储 搜索推荐 Java
【排序算法】冒泡排序、选择排序、插入排序
【排序算法】冒泡排序、选择排序、插入排序
79 0
【排序算法】冒泡排序、选择排序、插入排序
|
算法 搜索推荐
常见排序算法之交换排序——冒泡排序、快速排序
​ 哈喽大家好,我是保护小周ღ,本期为大家带来的是常见排序算法中的交换排序,主要有冒泡排序,快速排序,快排分享了三种算法:挖坑法,左右指针法,前后指针法,以及两种优化方式:解决快排最坏情况的“三数取中”,避免递归次数过多的"小区间优化",包您一看就会,快来试试吧~ ​