排序(冒泡插排选排)

6 篇文章 0 订阅
3 篇文章 0 订阅
本文详细介绍了三种经典的排序算法:插入排序、选择排序和冒泡排序。分别阐述了它们的原理、代码实现、性能分析以及稳定性。在时间复杂度上,这三种算法在最坏情况下均为O(n^2),而插入排序和冒泡排序在最好情况下能达到O(n)。此外,插入排序和冒泡排序是稳定的排序算法,但选择排序不是。这些基础知识对于理解和优化算法效率至关重要。
摘要由CSDN通过智能技术生成

排序 就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。
平时的上下文中,如果提到排序,通常指的是排升序(非降序)。
通常意义上的排序,都是指的原地排序(in place sort)。

稳定性 指两个相等的数据,如果经过排序后,排序算法能保证其相对位置不发生变化,则我们称该算法是具备稳
定性的排序算法。
在这里插入图片描述
基于比较的七种排序
在这里插入图片描述

插入排序

原理
整个区间被分为

  1. 有序区间
  2. 无序区间
    每次选择无序区间的第一个元素,在有序区间内选择合适的位置插入

代码实现

 // 最好的情况:数组有序
    // 最坏的情况:数组倒序
    // 最好情况的时间复杂度:O(n)
    // 最坏情况的时间复杂度:O(n ^ 2)
    // 平均情况的时间复杂度:O(n ^ 2)
    // 能否保证稳定性:能保证稳定性
    // 空间复杂度:O(1)
    public static void insertSort(long[] array) {
        for (int i = 1; i < array.length; i++) {
            // 有序区间: [0, i)
            // 无序区间: [i, array.length)

            // 1. 把无序区间的第一个数 [i] 插入到有序区间
            long key = array[i];
            int j;
            for (j = i - 1; j >= 0 && array[j] > key; j--) {
                array[j + 1] = array[j];
            }
//            for (j = i - 1; j >= 0; j--) {
//                if (array[j] < key) {
//                    // key 应该插入到 [j + 1]
//                    break;
//                } else if (array[j] == key) {
//                    // key 应该插入到 [j + 1]
//                    break;
//                } else {
//                    // j 继续往前
//                }
//
//                array[j + 1] = array[j];
//            }

            array[j + 1] = key;
        }
    }

性能分析
最好的情况:数组有序
最坏的情况:数组倒序
最好情况的时间复杂度:O(n)
最坏情况的时间复杂度:O(n ^ 2)
平均情况的时间复杂度:O(n ^ 2)
能否保证稳定性:能保证稳定性
空间复杂度:O(1)

选择排序

原理
每一次从无序区间选出最大(或最小)的一个元素,存放在无序区间的最后(或最前),直到全部待排
序的数据元素排完 。
代码实现

// 不区分最好/平均/最坏情况
    // 时间复杂度:O(n ^ 2)
    // 空间复杂度:O(1)
    // 能否保证稳定性:不能保证稳定性
    public static void selectSort(long[] array) {
        for (int i = 0; i < array.length - 1; i++) {
            // 无序区间: [0, array.length - i)

            // 在无序区间中,找出最大的数所在的下标
            // 通过遍历查找
            int maxIndex = -1;
            for (int j = 0; j < array.length - i; j++) {
                if (maxIndex == -1 || array[j] > array[maxIndex]) {
                    maxIndex = j;
                }
            }

            // 交换 最大数[maxIndex] 和 无序区间的最后一个数[array.length - i - 1]
            swap(array, maxIndex, array.length - i - 1);
        }
    }

性能分析
不区分最好/平均/最坏情况
时间复杂度:O(n ^ 2)
空间复杂度:O(1)
能否保证稳定性:不能保证稳定性

冒泡排序

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

// 最好的情况:数组有序
    // 最坏的情况:数组倒序
    // 最好情况的时间复杂度:O(n)
    // 最坏情况的时间复杂度:O(n ^ 2)
    // 平均情况的时间复杂度:O(n ^ 2)
    // 能否保证稳定性:能保证稳定性
    // 空间复杂度:O(1)
    public static void bubbleSort(long[] array) {
        for (int i = 0; i < array.length - 1; i++) {
            // 无序区间: [0, array.length - i)

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

            // 执行一次冒泡过程 —— 需要比较无序区间元素的次数 - 1 次
            for (int j = 0; j < array.length - i - 1; j++) {
                if (array[j] > array[j + 1]) {
                    swap(array, j , j + 1);
                    sorted = false;
                }
            }

            if (sorted) {
                // 假设成立,无序区间确实已经有序了
                return;
            }
        }
    }

性能分析
最好的情况:数组有序
最坏的情况:数组倒序
最好情况的时间复杂度: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、付费专栏及课程。

余额充值