IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【Java】5大排序算法总结(插入排序+希尔排序+选择排序+堆排序+冒泡排序) -> 正文阅读

[数据结构与算法]【Java】5大排序算法总结(插入排序+希尔排序+选择排序+堆排序+冒泡排序)

1. 稳定性

两个相等的数据,如果经过排序后,排序算法能保证其相对位置不发生变化,则我们称该算法是具备稳定性的排序算法。
在这里插入图片描述
图中排序后a仍然在b前面,此时这个排序就是稳定的。

常见的排序算法有 :
在这里插入图片描述

2 . 插入排序

步骤:

  1. 从第一个元素开始,该元素可以认为已经被排序
  2. 取下一个元素下标定义为i,并且放到变量tmp中,从已排序的元素序列从后往前扫描
  3. 如果该元素大于tem,则将该元素移到下一位
  4. 重复步骤3,直到找到已排序元素中小于等于tem的元素,直接break
  5. tem插入到该元素的后面(array[j+1]=tmp;),如果已排序所有元素都大于tem,则将tem插入到下标为0的位置
  6. 重复步骤2~5
 /**
     * 直接插入排序
     * 时间复杂度:O(N^2) 逆序的时候
     * (最好的情况是O(N):对于直接插入排序来说,最好的情况就是数组有序的时候)
     * 根据这个结论:推导出另一个结论:对于直接插入排序来说,数据越有序,越快
     * 直接插入排序所以也用于其他排序的优化!
     * 空间复杂度:O(1)
     * 稳定性:稳定
     * 一个稳定的排序,可以实现一个不稳定的排序
     * 但是一个本身就不稳定的排序就不可以变成稳定的排序
     * 经常使用在 数据量不多 且 整体数据趋于有序了
     * @param array
     */
    public void insertSort(int[] array){
        for (int i =1 ; i <array.length ; i++) {
            int tmp=array[i];
            int j=i-1;
            for (; j>=0 ; j--) {
                if (array[j]>tmp){
                    array[j+1]=array[j];
                }else {
                    // 只要j回退的时候,遇到了比tmp小的元素,就结束这次的比较
                    break;
                }
            }
            //j回退到了 小于0 的地方
            array[j+1]=tmp;
        }
    }

动图演示如下:
请添加图片描述

3. 希尔排序

步骤:

  1. 先选定一个小于N的整数gap作为第一增量,然后将所有距离为gap的元素分在同一组,并对每一组的元素进行直接插入排序。然后再取一个比第一增量小的整数作为第二增量,重复上述操作…
  2. 当增量的大小减到1时,就相当于整个序列被分到一组,进行一次直接插入排序,排序完成。
  /**
     * 希尔排序
     * 时间复杂度:O(N^1.3-N^1.5)
     * 空间复杂度:O(1)
     * 稳定性 : 不稳定的
     *  看在比较的过程当中,是否发生了跳跃式的交换,如果发生了跳跃式的交换 那么就是不稳定的排序
     *  (基本上没有考过)
     *
     * @param array
     * @param gap 组数
     */
    public static void shell(int[] array,int gap){
        for (int i =gap ; i <array.length ; i++) {
            int tmp=array[i];
            int j=i-gap;
            for (; j>=0 ; j-=gap) {
                if (array[j]>tmp){
                    array[j+gap]=array[j];
                }else {
                    // 只要j回退的时候,遇到了比tmp小的元素,就结束这次的比较
                    break;
                }
            }
            //j回退到了 小于0 的地方
            array[j+gap]=tmp;
        }
    }
    public static void shellSort(int[] array){
        int gap=array.length;
        while (gap>1){
            shell(array,gap);
            gap/=2;
        }
        shell(array,1);
    }

动图演示如下:
请添加图片描述

4. 选择排序

思路:
每次从待排序列中选出一个最小值,然后放在序列的起始位置,直到全部待排数据排完即可。

实际上,我们可以一趟选出两个值,一个最大值一个最小值,然后将其放在序列开头和末尾,这样可以使选择排序的效率快一倍。

/**
     * 选择排序
     * 时间复杂度:O(N^2)
     * 空间复杂度:O(1)
     * 稳定性:不稳定的排序
     * @param array
     */
    public static void swap(int[] array,int i,int j){
        int tmp=array[i];
        array[i]=array[j];
        array[j]=tmp;
    }

    //优化选择排序:每次交换都是当前遍历j时候的最小值

    public static void selectSort1(int[] array){
        for (int i = 0; i < array.length; i++) {
            int minIndex=i;
            for (int j = i+1; j < array.length ; j++) {
                if (array[j]<array[minIndex]){
                    minIndex=j;
                }
            }
            swap(array,i,minIndex);
        }

    }

    public static void selectSort(int[] array) {
        for (int i = 0; i < array.length; i++) {
            for (int j = i + 1; j < array.length; j++) {
                if (array[i] > array[j]) {
                    int tmp = array[i];
                    array[i] = array[j];
                    array[j] = tmp;
                }
            }
        }
    }

动图演示如下 :
请添加图片描述

5. 堆排序

基本原理也是选择排序,只是不在使用遍历的方式查找无序区间的最大的数,而是通过堆来选择无序区间的最大的数。
注意: 排升序要建大堆;排降序要建小堆。

堆排序可以参考之前写的一篇博文:堆详解

也可以借鉴大佬的一篇关于堆排的文章,博主看了受益匪浅:堆排序

/**
     * 堆排序  排升序要建大堆;排降序要建小堆。
     * 时间复杂度 :O(N*logN)
     * 空间复杂度 : O(1)
     * 稳定性:不稳定的
     *
     * @param array
     */
    public static void heapSort(int[] array){
        //1.建堆 O(N)
        creatHeap(array);
        int end=array.length-1;
        //2.交换然后向下调整为大根堆 O(N*logN)
        while (end>0){
            swap(array,0,end);
            shiftDown(array,0,end);
            end--;
        }
    }

    public static void creatHeap(int[] array){
        for (int parent = (array.length-1-1)/2; parent >= 0 ; parent--) {
            shiftDown(array,parent,array.length);
        }
    }

    public static void shiftDown(int[] array,int parent,int len){
        int child=2*parent+1; //左孩子
        while (child<len){
            if (child+1<len && array[child]<array[child+1]){
                child++; //保证child下标,就是左右孩子最大值下标
            }
            if (array[child]>array[parent]){
                swap(array,child,parent);
                parent=child;
                child=2*parent+1;
            }else {
                break;
            }
        }
    }

算法图解 :
请添加图片描述

6 冒泡排序

原理:
在无序区间,通过相邻数的比较,将最大的数冒泡到无序区间的最后,持续这个过程,直到数组整体有序

思路:
排序一趟可以让最大的数字沉底
排序len-1趟,一趟排序len-1-i次
详细实现看代码


    /**
     * 冒泡排序(未优化)
     * 时间复杂度:O(N^2)
     * 空间复杂度:O(1)
     * 稳定性:稳定的排序
     * @param array
     */
    public static void bubbleSort(int[] array){
        for (int i = 0; i < array.length-1; i++) {
            for (int j = 0; j < array.length-1; j++) {
                if (array[j]>array[j+1]){
                    swap(array,j,j+1);
                }
            }

        }
    }


    /**
     * 冒泡排序(优化)
     * 时间复杂度:O(N^2) (最坏的情况)
     * (最好的情况 : 有序)  O(N)
     * 空间复杂度:O(1)
     * 稳定性:稳定的排序
     * @param array
     */

    public static void bubbleSort2(int[] array){
        for (int i = 0; i < array.length-1; i++) {
            boolean flg=false;
            for (int j = 0; j < array.length-1-i; j++) {
                if (array[j]>array[j+1]){
                    swap(array,j,j+1);
                    flg=true;
                }
            }
            if (flg==false){ //没交换的话说明flg没被制成TRUE,则说明已经有序,可以跳出循环了
                break;
            }
        }
    }

动图演示如下 :
请添加图片描述

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-02-16 13:22:22  更:2022-02-16 13:23:25 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 17:37:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码