[Java]各種基礎的查詢和排序演算法總結
阿新 • • 發佈:2019-01-30
查詢方法:
1.順序查詢。
按陣列的順序從前往後一直比較,直到找到目標值返回。
優點:對陣列的結構沒有特定的要求,演算法簡單。
缺點:當陣列個數n較大時,效率低下。
時間複雜度:最大時間複雜度是O(n),最小時間複雜度是O(1),平均時間複雜度是O(n/2).
2.二分查詢:
從陣列的中間開始查詢,若找到目標值則返回;若目標值比中間數小則遞迴查詢前半部分;若目標值比中間數大則遞迴查詢後半部分。
優點:比較次數較少,效率比較高
缺點:只適用於不經常變動有序陣列
排序方法:
1.插入排序:
將一個數據插入到已經排好序的有序資料中,在有序序列中選出合適的位置插入,從而得到一個新的、個數加一的有序資料。
優點:是穩定的排序方法。
缺點:演算法適用於少量資料的排序
時間複雜度為O(n^2)。
2.氣泡排序
每次將相鄰的兩個數進行比較,如果想升序,則大數往後,反之亦然。
優點:演算法簡單,穩定演算法
缺點:效率低下的排序方法,在資料規模很小時,可以採用;
時間複雜度:無序O(n^2),有序o(1)
3.歸併排序
採用分治的思想,通過分割和合並,達到目的
優點:演算法簡單,穩定演算法
平均時間複雜度:O(nlog2n)
4.快速排序
1.先從數列中取出一個數作為基準數。
2.分割槽過程,將比這個數大的數全放到它的右邊,小於或等於它的數全放到它的左邊。
3.再對左右區間重複第二步,直到各區間只有一個數。
是不穩定的演算法
1.順序查詢。
按陣列的順序從前往後一直比較,直到找到目標值返回。
優點:對陣列的結構沒有特定的要求,演算法簡單。
缺點:當陣列個數n較大時,效率低下。
時間複雜度:最大時間複雜度是O(n),最小時間複雜度是O(1),平均時間複雜度是O(n/2).
<span style="white-space:pre"> </span>/** * 順序查詢演算法 * * @param array * 陣列 * @param target * 目標 * @return 找到,返回下標值;找不到返回0x80000000 */ public int sequentialSearch(int[] array, int target) { if (array == null) { throw new NullPointerException("the array can't not be null!"); } if (array.length <= 0) { throw new IllegalArgumentException("the length of array is illgal!"); } for (int index = 0; index < array.length - 1; index++) { if (array[index] == target) { return index; } } return Integer.MIN_VALUE; }
2.二分查詢:
從陣列的中間開始查詢,若找到目標值則返回;若目標值比中間數小則遞迴查詢前半部分;若目標值比中間數大則遞迴查詢後半部分。
優點:比較次數較少,效率比較高
缺點:只適用於不經常變動有序陣列
時間複雜度:O(log(n))
/** * 二分查詢演算法 * @param array 有序陣列 * @param target 目標數值 * @return 找到,返回下標值;找不到返回0x80000000 */ public int binarySearch(int[] array, int target) { if (array == null) { throw new NullPointerException("the array can't not be null!"); } if (array.length <= 0) { throw new IllegalArgumentException("the length of array is illgal!"); } int low = 0; int high = array.length - 1; while (low <= high) { int middle = (low + high) / 2; if (target == array[middle]) { return middle; } if (target > array[middle]) { low = middle + 1; } else { high = middle - 1; } } return Integer.MIN_VALUE; }
排序方法:
1.插入排序:
將一個數據插入到已經排好序的有序資料中,在有序序列中選出合適的位置插入,從而得到一個新的、個數加一的有序資料。
優點:是穩定的排序方法。
缺點:演算法適用於少量資料的排序
時間複雜度為O(n^2)。
<span style="white-space:pre"> </span>public int[] insertSort(int[] array) { if (array == null) { throw new NullPointerException("the array can't not be null!"); } if (array.length <= 0) { throw new IllegalArgumentException("the length of array is illgal!"); } for (int i = 0; i < array.length - 1; i++) { int index = halfFindIndex(array, array[i], i); if (index != i) { int temp = array[i]; for (int j = i; j > index; j--) { array[j] = array[j - 1]; } array[index] = temp; } } return array; } private int halfFindIndex(int[] array, int target, int end) { int low = 0; int high = end; int middle = 0; while (low <= high) { middle = (low + high) / 2; if (target < array[middle]) { low = middle + 1; } else { high = middle - 1; } } if (target > array[middle]) { middle++; } return middle; }
2.氣泡排序
每次將相鄰的兩個數進行比較,如果想升序,則大數往後,反之亦然。
優點:演算法簡單,穩定演算法
缺點:效率低下的排序方法,在資料規模很小時,可以採用;
時間複雜度:無序O(n^2),有序o(1)
<span style="white-space:pre"> </span>public int[] bubbleSort(int[] array) {
if (array == null) {
throw new NullPointerException("the array can't not be null!");
}
if (array.length <= 0) {
throw new IllegalArgumentException("the length of array is illgal!");
}
int flag = array.length - 1;
while (flag > 0) {
int end = flag;
flag = 0;
for (int i = 0; i < end; i++) {
if (array[i] > array[i + 1]) {
int temp = array[i + 1];
array[i + 1] = array[i];
array[i] = temp;
flag = i;
}
}
}
return array;
}
3.歸併排序
採用分治的思想,通過分割和合並,達到目的
優點:演算法簡單,穩定演算法
平均時間複雜度:O(nlog2n)
空間複雜度:O(n) (用於儲存有序子序列合併後有序序列)
/**
* 歸併排序
*
* @param unSortArray
* @return
* @throws NullPointerException
* @throws IllegalArgumentException
*/
public int[] mergerSort(int[] unSortArray) throws NullPointerException,
IllegalArgumentException {
if (unSortArray == null) {
throw new NullPointerException("the array is null!");
}
if (unSortArray.length <= 0) {
throw new IllegalArgumentException("the size of array is illgal!");
}
int last = unSortArray.length - 1;
int[] temp = new int[unSortArray.length];
return merger(unSortArray, 0, last, temp);
}
/**
* 遞迴實現歸併排序
*
* @param unSortArray
* 無序陣列
* @param first
* 開始下標
* @param last
* 最後有效下標
*/
private int[] merger(int[] unSortArray, int first, int last, int[] temp) {
if (temp == null) {
return null;
}
if (first < last) {
int middle = (first + last) / 2;
// 左邊
merger(unSortArray, first, middle, temp);
// 右邊
merger(unSortArray, middle + 1, last, temp);
// 排序
mergerArray(unSortArray, first, middle, last, temp);
}
return unSortArray;
}
/**
* 將兩個有序序列合併成一個有序序列
*
* @param array
* 一個無序序列
* @param first
* 開始的座標
* @param last
* 最後的座標
* @param temp
* 暫存陣列
*/
private void mergerArray(int[] array, int first, int mid, int last,
int[] temp) {
int start = first;
int latterIndex = mid + 1;
int tempIndex = 0;
while (start <= mid && latterIndex <= last) {
// 比較將數放進暫存陣列中
if (array[start] < array[latterIndex]) {
temp[tempIndex++] = array[start++];
} else {
temp[tempIndex++] = array[latterIndex++];
}
}
while (start <= mid) {
// 將middle以前的有序序列暫存到陣列中
temp[tempIndex++] = array[start++];
}
while (latterIndex <= last) {
// 將middle以後的有序序列暫存到陣列中
temp[tempIndex++] = array[latterIndex++];
}
for (int i = 0; i < tempIndex; i++) {
// 將暫存數組裡的數複製到一開始的無序序列中
array[first + i] = temp[i];
}
}
4.快速排序
1.先從數列中取出一個數作為基準數。
2.分割槽過程,將比這個數大的數全放到它的右邊,小於或等於它的數全放到它的左邊。
3.再對左右區間重複第二步,直到各區間只有一個數。
是不穩定的演算法
快速排序時間複雜度下界為O(nlgn),最壞情況為O(n^2)。在實際應用中,快速排序的平均時間複雜度為O(nlgn)
只要對快速排序做簡單的操作,就能使時間複雜度總是O(nlgn):
1.對排序資料進行打亂;
2.隨機挑選基準數.
額外空間O(log(n))
<span style="white-space:pre"> </span>public int[] quickSort(int[] unSortArray, int left, int right)
throws NullPointerException, IllegalArgumentException {
if (unSortArray == null) {
throw new NullPointerException("the array is null!");
}
if (unSortArray.length <= 0) {
throw new IllegalArgumentException("the size of array is illgal!");
}
if (left < right) {
int start = left;
int end = right;
// 選第一個為基準
int x = unSortArray[start];
while (start < end) {
while (start < end && x < unSortArray[end]) {
// 找到小於基準的數
end--;
}
if (start < end) {
// 交換位置
unSortArray[start] = unSortArray[end];
start++;
}
while (start < end && x > unSortArray[start]) {
// 找到大於基準的數
start++;
}
if (start < end) {
// 交換位置
unSortArray[end] = unSortArray[start];
end--;
}
}
unSortArray[start] = x;
quickSort(unSortArray, left, start - 1); // 遞迴呼叫
quickSort(unSortArray, start + 1, right);
}
return unSortArray;
}