【数据结构】Java实现各类经典排序算法——选择排序、冒泡排序

一、选择排序

    顾名思义,选择排序就是每次选出待选数组中最大的元素,放到待选数组右侧即可。为了实现O(1)的空间复杂度呢,这个放到右侧的操作通过元素在数组间交换来进行。

    第一次扫描整个大小为n的数组,最大的放数组最右边;此后从左到右扫描数组前n-1、n-2...项,因为数组右端已经排序完成。下面是代码实现:

    public void chooseSort(int[] nums) {
        // 选择排序
        for(int j = nums.length - 1; j > 0; j--) {
            int maxIndex = 0;
            for(int i = 1; i <= j; i++) {
                if(nums[i] > nums[maxIndex]) {
                    maxIndex = i;
                }
            }
            swap(nums, j, maxIndex);
        }
    }

    时间复杂度:代码有两重for循环,而且无论什么情况下循环都不会提前中止。因此最坏、最好情况下,时间复杂度均为O(n2);空间复杂度:显然为O(1);稳定性:当原数组中有大小相同的元素时,相同元素最左一个在排序过程中会被换到右边去,因此不稳定。


二、冒泡排序

    这应该是很多同学接触最早的排序算法了。和选择排序类似,冒泡排序保证每一趟排序后,找出最大的元素放到数组最右侧,只是实现方案不同。选择排序通过缓存、更新最大元素的index,最终把index对应元素一次交换到最右方进行;冒泡排序则通过控制相邻元素的交换与不交换来把最大元素转移到右侧。以下是实现代码:

    public void bubbleSort(int[] nums) {
        // 冒泡排序
        for(int i = nums.length - 1; i > 0; i--) {
            boolean flag = true;  // 若此处不加flag位来提前结束,则算法循环结构与选择排序完全一致,最好情况下复杂度也为二次
            for(int j = 1; j <= i; j++) {
                if(nums[j-1] > nums[j]) {
                    swap(nums, j-1, j);
                    flag = false;
                }
            }
            if(flag) {
                break;
            }
        }
    }

    时间复杂度:可以看出,冒泡排序的循环结构和选择排序是类似的,但在数组整体已经有序的情况下可以提前结束循环。因此最好情况为O(n)、最差为O(n2)、平均为O(n2);空间复杂度:O(1);稳定性:数组中有相同大小元素时,相同大小元素若不相邻,则会在排序过程中被逐渐交换到相邻,过程中相对位置明显不改变。相邻之后,相同大小元素区间内不会再进行交换,因此算法稳定。

    在原数组“基本有序”的情况下,冒泡排序时间复杂度可以接近线性。反序情况下,与选择排序同为O(n2)时间复杂度,且因为交换次数过多,效率低于选择排序。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值