排序算法(基础排序算法)

选择排序

选择排序的基本思想:

每一轮选取未排定的部分中 最小的元素交换到未排定部分的最开头,经过若干个步骤,就能排定整个数组。

参考代码:

//选择排序
public class Selectionsort {
    public int[] sortArray(int[] nums) {
        int len = nums.length;

        //当数组的长度小于2(即长度为0或者1)时,直接返回该数组;
        if (len < 2) {
            return nums;
        }

        for (int i = 0; i < len; i++) {
            //在nums[i...len-1]中选出最小的元素
            for (int j = i + 1; j < len; j++) {
                if (nums[j] < nums[i]) {
                    int temp = nums[i];
                    nums[i] = nums[j];
                    nums[j] = temp;
                }
            }
        }
        return nums;
    }
}

冒泡排序

冒泡排序的基本思想

两两比较相邻两个位置的元素,把较大的元素交换到上方;
每一轮都会把当前最大的元素冒泡到数组的末尾。

「选择排序」和「冒泡排序」的区别:

「冒泡排序」每一轮的确是选出最值,但它是通过两两比较和交换,把最值元素渐渐地交换到数组的末尾,每一轮选出最值,需要交换多次;

「选择排序」每一轮选出最小值,交换到数组的前面,每一轮只交换一次。

参考代码:

//冒泡排序
public class BubbleSort {
    public int[] sortArray(int[] nums) {
        int len = nums.length;
        for (int i = 0; i < len - 1; i++) {
            for (int j = 1; j < len; j++) {
                if (nums[j - 1] > nums[j]) {
                    int temp = nums[j - 1];
                    nums[j - 1] = nums[j];
                    nums[j] =temp;
                }
            }
        }
        return nums;
    }
 }

冒泡排序的优化

如果在一次循环中,都没有「冒泡」行为发生,整个排序任务就可以提前终止。

优化参考代码:

//冒泡排序优化
public class BubbleSort {
    public int[] sortArray(int[] nums) {
        int len = nums.length;
        for (int i = 0; i < len - 1; i++) {
        /*可以设置布尔变量 sorted,假设每一轮循环开始假设数组是有序的; 
        一旦在比较的过程中执行了交换,说明数组不是有序的,将 sorted 设置为 false; 
        如果在一次循环中,都没有「冒泡」行为发生,才可以认为剩下的部分是有序的.*/
            boolean sorted = true;
            for (int j = 1; j < len; j++) {
                if (nums[j - 1] > nums[j]) {
                    sorted = false;
                    int temp = nums[j - 1];
                    nums[j - 1] = nums[j];
                    nums[j] = temp;
                }
            }
            if (sorted) return  nums;
        }
        return nums;
    }
}

插入排序

插入排序的基本思想

插入排序每一次将一个元素插入到它前面的有序数组中。

参考代码:

//插入排序
public class Insertionsort {
    public int[] sortArray(int[] nums) {
        int len = nums.length;
        //把 nums[i] 插入有序数组 nums[0...i-1]中
        for (int i = 1; i < len; i++) {
            for (int j = i; j > 0; j--) {
                if (nums[j] < nums[j - 1]) {
                    int temp = nums[j];
                    nums[j] = nums[j - 1];
                    nums[j - 1] = temp;
                } else {
                    break;
                }
            }
        }
        return nums;
    }
}

插入排序的意义

「插入排序」是稳定排序,在数组的值 接近有序 的情况下,表现优异。

在小区间内执行排序任务的时候,可以转向使用「插入排序」。

归并排序和快速排序是基于分治算法的排序算法;归并排序和快速排序拆分到较小区间的时候转而使用插入排序(在绝大多数情况下,插入排序应用长度为6到16之间的任意的排序任务上都能令人满意).

插入排序很多时候成为了高级排序算法的底层的算法.(高级排序算法的底层会转向使用插入排序)

插入排序的优化

//插入排序优化
public class Insertionsort {
    public int[] sortArray(int[] nums) {
        int len = nums.length;
        // 循环不变量:将 nums[i] 插入到区间 [0..i) 使之成为有序数组
        for (int i = 1; i < len; i++) {
            // 先暂存这个元素,然后之前元素逐个后移,留出空位
            int temp = nums[i];
            int j = i;
            // 注意边界 j > 0
            while (j > 0 && nums[j - 1] > temp) {
                nums[j] = nums[j - 1];
                j--;
            }
            nums[j] = temp;
        }
        return nums;
    }
}

希尔排序

希尔排序的基本思想

开始的时候逐渐让数组变得基本有序,最后使用一次使用「插入排序」就变得高效了。

希尔排序是 「分组插入排序」 或者 「带间隔的插入排序」。

好处是:让较小的元素一下子来到数组的前面。 每一轮完成一次分组插入排序以后,数组就朝着接近有序的方向前进了一步。最后一轮一定是一次标准的插入排序。

参考代码:

//希尔排序
public class Hillsort {

    public int[] sortArray(int[] nums) {
        int len = nums.length;
        for (int detal = len / 2; detal > 0; detal /= 2) {
            for (int start = 0; start < detal; start++) {
                insertionSortForDetal(nums, len, detal, start);
            }
        }
        return nums;
    }

    private void insertionSortForDetal(int[] nums, int len, int detal, int start) {
        for (int i = start + detal; i < len; i += detal) {
            int temp = nums[i];
            int j = i;
            for (; j - detal >= 0; j -= detal) {
                if (nums[j - detal] > temp) {
                    nums[j] = nums[j - detal];
                } else {
                    break;
                }
            }
            // 此时 nums[j - 1] <= temp
            // nums[j] 的值被赋值到了 nums[j + 1]
            nums[j] = temp;
        }
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值