在面試過程中,筆試環節經常要求手寫一種或者幾種排序算法。如果你還不會寫,可能就要被其他的同學給刷下去啦。希望這篇文章能幫到你。
本文實現了三種基本的排序算法:冒泡排序,插入排序,選擇排序。並簡單的闡述了各自的排序流程以及時間複雜度。
注:
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));
}
}
全文完。如果你發現文中有可以改進或者錯誤的地方,請在下方評論中指出,非常感謝~