算法——蛮力法之选择/冒泡/插入排序

选择/冒泡/插入排序

排序算法简介

排序是数据处理中十分常见且核心的操作,虽说实际项目开发中很小几率会需要手动实现,但是了解这些精妙的思想对我们还是大有裨益的。本文介绍最基础的三类算法:选择,冒泡,插入。

交换数组元素

排序算法中经常用到交换数组元素的操作,所以我们预先定义好这个函数swap

/**
     * 交换数组元素
     * @param arr
     * @param a
     * @param b
     */
    public static void swap(int []arr,int a,int b){
        arr[a] = arr[a]+arr[b];
        arr[b] = arr[a]-arr[b];
        arr[a] = arr[a]-arr[b];
    }

选择排序

选择排序策略

选择排序基本思想为每一趟从待排序的数据元素中选择最小(或最大)的一个元素作为首元素,直到所有元素排完为止

选择排序基本步骤

在算法实现时,为了确定我们需要的最小元素,我们设置一个变量min,每一次比较仅存储较小元素的数组下标,当遍历环结束之后,那这个变量存储的就是当前最小元素的下标,此时再执行交换操作即可,相对于每次比较之后都交换,这样做效率较高

/**
     * 简单选择排序
     *
     * @param arr
     */
    public static void selectSort(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            int min = i;//每一趟循环比较时,min用于存放较小元素的数组下标,这样当前批次比较完毕最终存放的就是此趟内最小的元素的下标,避免每次遇到较小元素都要进行交换。
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[j] < arr[min]) {
                    min = j;
                }
            }
            //进行交换,如果min发生变化,则进行交换
            if (min != i) {
                swap(arr,min,i);
            }
        }
    }

选择排序算法分析

选择排序的比较次数是不变的;对于交换操作,在最好情况下也就是数组完全有序的时候,无需任何交换移动,在最差情况下,也就是数组倒序的时候,交换次数为n-1次。所以选择排序的时间复杂度为O(n2)

  • 选择排序无需用到多余的空间和数据结构,所以是原地的
  • 选择排序一般采用数组实现,所以是不稳定的

冒泡排序

冒泡排序策略

冒泡排序的基本思想是,对相邻的元素进行两两比较,顺序相反则进行交换,这样,每一趟会将最小或最大的元素“浮”到顶端,最终达到完全有序

冒泡排序基本步骤

冒泡排序

/**
     * 冒泡排序
     *
     * @param arr
     */
    public static void bubbleSort(int[] arr) {
        for (int i = 0; i < arr.length - 1; i++) {
            boolean flag = true;//设定一个标记,若为true,则表示此次循环没有进行交换,也就是待排序列已经有序,排序已然完成。
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    swap(arr,j,j+1);
                    flag = false;
                }
            }
            if (flag) {
                break;
            }
        }
    }

冒泡排序算法分析

根据冒泡排序的实现,若原数组本身就是有序的(这是最好情况),仅需n-1次比较就可完成;若是倒序,比较次数为 n-1+n-2+…+1=n(n-1)/2,交换次数和比较次数等值。所以,其时间复杂度依然为O(n2)。综合来看,冒泡排序性能还是稍差于选择排序的。

  • 冒泡排序无需用到多余的空间和数据结构,所以是原地的
  • 冒泡排序是否稳定主要取决于交换的原则(等于时是否交换)

插入排序

插入排序策略

插入排序基本思想是每一步将一个待排序的记录,插入到前面已经排好序的有序序列中去,直到插完所有元素为止。

插入排序基本步骤

比较从有序序列的最后一个元素开始,如果比它大则直接插入在其后面,否则一直往前比,直到找到这个元素应该在的位置
插入排序

/**
     * 插入排序
     *
     * @param arr
     */
    public static void insertionSort(int[] arr) {
        for (int i = 1; i < arr.length; i++) {
            int j = i;
            while (j > 0 && arr[j] < arr[j - 1]) {
                swap(arr,j,j-1);
                j--;
            }
        }
    }

插入排序性能分析

插入排序在最好情况下,需要比较n-1次,无需交换元素,时间复杂度为O(n);在最坏情况下,时间复杂度依然为O(n2)。但是在数组元素随机排列的情况下,插入排序优于上面两种排序。

  • 插入排序无需用到多余的空间和数据结构,所以是原地的
  • 如果找到一个和当前位置相等的元素,那么就将目标元素插入到这个相等元素的后面,所以不会改变等值元素的相对顺序,插入排序是稳定的
发布了9 篇原创文章 · 获赞 0 · 访问量 176

猜你喜欢

转载自blog.csdn.net/qq_36629741/article/details/104678395