排序算法(基礎排序算法:冒泡、插入、選擇)

在面試過程中,筆試環節經常要求手寫一種或者幾種排序算法。如果你還不會寫,可能就要被其他的同學給刷下去啦。希望這篇文章能幫到你。

本文實現了三種基本的排序算法:冒泡排序,插入排序,選擇排序。並簡單的闡述了各自的排序流程以及時間複雜度。

注:

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));
    }
}

全文完。如果你發現文中有可以改進或者錯誤的地方,請在下方評論中指出,非常感謝~

 

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