算法的入门-排序算法

158 阅读2分钟

十大排序算法

  • 选择排序、冒泡排序、插入排序、希尔排序。
  • 归并排序和快速排序。
  • 堆排序。
  • 非比较排序:计数排序、基数排序、桶排序。

可以打开这个 网站,体验一下各种排序算法。

以「力扣」第 912 题:排序数组 为例,实现自己的排序算法,提交给这一题的测试用例,检验学习成果。

选择排序

思路:每一轮选取未排定的部分中 最小 的元素交换到未排定部分的最开头,经过若干个步骤,就能排定整个数组。即:先选出最小的,再选出第 2 小的,以此类推。

class Solution {
    //在「力扣」运行超时
    public int[] sortArray(int[] nums) {
        int length = nums.length;

        for(int i=0;i< length;i++){
            // 用于标示最小值下标
            int minIndex = i;
            // 循环方式找到最小值
            for (int j = i + 1; j < length; j++) {
                if (nums[j] < nums[minIndex]) {
                    minIndex = j;
                }
            }
            swap(nums, i, minIndex);
        }

        return nums;

    }

    private void swap(int[] nums, int index1, int index2) {
        int temp = nums[index1];
        nums[index1] = nums[index2];
        nums[index2] = temp;
    }
}

复杂度分析

  • 时间复杂度:O(N^2),这里 N 是数组的长度。
  • 空间复杂度:O(1),使用到常数个临时变量。

冒泡排序

思路:

  • 相邻的两个元素进行比较,把比较大的元素排在后面,这样遍历一轮下来,就可以找到这一轮循环中最大的那个元素,我们把这个过程形象地称之为「冒泡」。

  • 由于每一轮循环都「冒泡」出一个这一轮循环最大的元素,所以上一轮循环的最后一个元素,不应该参加下一轮循环的比较了。

class Solution {
    // 在「力扣」运行超时
    public int[] sortArray(int[] nums) {
        int length = nums.length;

        for(int i= length -1 ;i >=0;i--){
            // 先默认数组是有序的,只要发生一次交换,就必须进行下一轮比较
            boolean sorted = true;
            for (int j = 0; j < i; j++) {
                if (nums[j] > nums[j+1]) {
                    swap(nums,j,j+1);
                    sorted = false;
                }
            }
            
            // 如果在内层循环中,都没有执行一次交换操作,说明此时数组已经是升序数组
            if(sorted){
                break;
            }
        }

        return nums;

    }

    private void swap(int[] nums, int index1, int index2) {
        int temp = nums[index1];
        nums[index1] = nums[index2];
        nums[index2] = temp;
    }
}

复杂度分析

  • 时间复杂度:O(N^2),这里 N 是数组的长度;
  • 空间复杂度:O(1),使用到常数个临时变量。

插入排序

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

  • 先暂存再后移:先暂存待插入元素,然后前面比暂存元素严格大的后移
class Solution {
    // 在数组「几乎有序」的前提下,「插入排序」的时间复杂度可以达到 O(N);
    public int[] sortArray(int[] nums) {
        int length = nums.length;


        for(int i= 1 ;i < length ;i++ ){
            int j= i;
            // 先暂存这个元素,然后之前元素逐个后移,留出空位
            int temp = nums[j];
            
            while(j >0 && nums[j -1] > temp){
                nums[j] = nums[j-1];
                j--;
            }
            nums[j] = temp;
            
        }

        return nums;

    }
}

复杂度分析

  • 时间复杂度:O(N^2),这里 N 是数组的长度;
  • 空间复杂度:O(1),使用到常数个临时变量。

归并排序

思路:

快速排序

堆排序

计数排序

基数排序

桶排序