排序算法(基础排序算法:冒泡、插入、选择)

在面试过程中,笔试环节经常要求手写一种或者几种排序算法。如果你还不会写,可能就要被其他的同学给刷下去啦。希望这篇文章能帮到你。

本文实现了三种基本的排序算法:冒泡排序,插入排序,选择排序。并简单的阐述了各自的排序流程以及时间复杂度。

注:

1.本文涉及到的排序均为升序排序,若要实现逆序,将内层for循环的比较符号反过来即可。

2.交换数组中的两个值比较简单,为了提高代码可读性,这里单独写了个swap()方法。

3.为了方便查看结果以理解排序过程,写了一个简单的dispaly()方法来展示数组。

package com.cai.common.utils;

import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * 提供几种常见的排序算法
 * 注:排序方式均为升序
 * Created by caidapao on 2018/4/5
 * Time 12:00
 */
@Component
public class SortUtil {

    public static void main(String args[]) {
        int test[] = {444, 666, 333, 888, 555, 999, 777, 222};
        SortUtil sortUtil = new SortUtil();
        //1.选择排序
        sortUtil.selectSort(test);
        //2.插入排序
        sortUtil.insertSort(test);
        //3.冒泡排序
        sortUtil.bubbleSort(test);
    }

    /**
     * 冒泡排序
     *
     * 1.排序过程:
     *   比较相邻两个值,若前面的大于后面的就进行交换。
     *   每一趟都会将最大的“冒泡”到后面,成为已经排序好的部分
     *
     * 2.时间复杂度:
     *   最好情况:O(n)
     *   最坏情况:O(n²)  ps:数组完全逆序,故比较次数为 n+(n-1)+(n-2)+...+1 由等差数列求和公式即可推导出。
     *
     * @param array 数组
     * @return 排序后的数组
     */
    public int[] bubbleSort(int[] array) {
        display("排序前:", array);
        for (int j = 0; j < array.length - 1; j++) {
            for (int i = 0; i < array.length - 1 - j; i++) {//注1,见下面冒泡排序过程展示
                if (array[i] > array[i + 1]) {
                    swap(i, i + 1, array);
                }
            }
            display("第" + (j + 1) + "趟:", array);
        }
        display("排序后:", array);
        return array;
    }

冒泡排序过程展示:

注1.内层for循环的判断条件经常会有同学错写成

i < array.length - 1  甚至是 i < array.length

前者没有搞清楚:每一趟排序过后,后面的999,888...都是已经排好的元素,已经不需要再排了,所以需要 - j来排除掉这些元素。这个问题还是比较严重的,会导致时间复杂度永远是O(n²),进行了没有意义的多余比较。

而后者相比前者,可能是没搞清楚冒泡排序是 相邻两个 比较。所以当排到倒数第二个的时候,其实已经排完了。


    /**
     * 插入排序
     *
     * 1.排序过程:
     *   默认将第一个元素认为是已排序,后面的认为是待排序的。
     *   始终将待排序的第一个元素(假定下标为 M),插入到已排序的合适的地方(假定下标为 K)的过程
     *   将数组下表为 K到 M-1 的值都往后挪动一位 ,再将 K 的值设为 M 的值
     *   重复此步骤直到 K=array.length-1
     *
     * 2.时间复杂度:
     *   最好情况:O(n)
     *   最坏情况:O(n²)
     * @param array 数组
     * @return 排序后的数组
     */
    public int[] insertSort(int[] array) {
        display("排序前:", array);
        for (int j = 1; j < array.length; j++) {
            for (int i = 0; i < j; i++) {
                if (array[j] < array[i]) {
                    int k = j;
                    int tempValue = array[j];
                    while (k > i) {
                        array[k] = array[k - 1];
                        k--;
                    }
                    array[i] = tempValue;
                }
            }
            display("第" + j + "趟:", array);
        }
        display("排序后:", array);
        return array;
    }

插入排序过程展示:


    /**
     * 选择排序
     *
     * 1.排序过程:
     *   第一趟,找出最小/大的放在第一位
     *   第二趟,从剩下的元素里找出最小/大的放在第二位
     *   ...
     *   第N趟,从剩下的元素里找出最小/大的放在第N位
     *
     * 2.时间复杂度:
     *   最好情况:O(n²)
     *   最坏情况:O(n²)
     *
     * @param array 数组
     * @return 排序后的数组
     */
    public int[] selectSort(int[] array) {
        display("排序前:", array);
        for (int j = 0; j < array.length - 1; j++) {
            int tempMinValue = array[j];
            int tempMinIndex = j;
            for (int i = j + 1; i < array.length; i++) {
                if (array[i] < tempMinValue) {
                    tempMinValue = array[i];
                    tempMinIndex = i;
                }
            }
            swap(tempMinIndex, j, array);
            display("第" + (j + 1) + "趟:", array);
        }
        display("排序后:", array);
        return array;
    }

选择排序过程展示:


    /**
     * 交换数组两个值
     * @param j 第一个数下标
     * @param i 第二个数下标
     * @param array 数组
     */
    private void swap(int j, int i, int[] array) {
        int temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }

    /**
     * 交换数组两个值(不需要开辟临时空间)
     * @param array 数组
     * @param j 第一个数下标
     * @param i 第二个数下标
     */
    private void swap(int[] array, int j, int i) {
        array[i] = array[j] + array[j];
        array[j] = array[i] - array[j];
        array[i] = array[i] - array[j];
    }

    /**
     * 数组展示
     * @param tip 提示语
     * @param array 数组
     */
    private void display(String tip, int[] array) {
        System.out.println(tip + Arrays.toString(array));
    }
}

全文完。如果你发现文中有可以改进或者错误的地方,请在下方评论中指出,非常感谢~

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章