簡單整理常用演算法,記錄在此。 package com.demo.sort; import java.util.Arrays; public class Sort { public static void main(String[] args) { int size = 10; int[] arr = ...
簡單整理常用演算法,記錄在此。
package com.demo.sort;
import java.util.Arrays;
public class Sort {
public static void main(String[] args) {
int size = 10;
int[] arr = new int[size];
for (int j = 0; j < size; j++) {
for (int i = 0; i < size; i++) {
arr[i] = (int) (100*size*Math.random() +1);
}
//測試冒泡
// System.out.println(Arrays.toString(bubble(arr)));
//測試選擇
// System.out.println(Arrays.toString(select(arr)));
//測試快速
// System.out.println(Arrays.toString(fast(arr,0,5)));
//測試插入排序
// System.out.println(Arrays.toString(insert(arr)));
//測試希爾排序
// System.out.println(Arrays.toString(shell(arr)));
//測試桶排序
// System.out.println(Arrays.toString(bucket(arr)));
//測試基數排序
// System.out.println(Arrays.toString(radix(arr)));
//測試歸併排序
// mergeSort(arr);
// System.out.println(Arrays.toString(arr));
//測試堆排序
// System.out.println(Arrays.toString(heap(arr)));
}
}
/**
* heap sort 堆排序原理(升序):
* 將序列抽象為二叉樹,構建最大堆;
* 依次將最大元素與待排序列的最後位置交換;
* 遍歷刷新直至最後一個元素;
* 演算法思想:完全二叉樹
* 時間複雜度:O[NlogN]
* 空間複雜度:O[1]
* 穩定性:不穩定
*/
private static int[] heap(int[] arr) {
for (int i = 0; i < arr.length; i++) {
maxHeap(arr, arr.length - i);
// 交換
int temp = arr[0];
arr[0] = arr[(arr.length - 1) - i];
arr[(arr.length - 1) - i] = temp;
}
return arr;
}
private static void maxHeap(int[] arr, int size) {
for (int i = size - 1; i >= 0; i--) {
buildheap(arr, i, size);
}
}
private static void buildheap(int[] arr, int rootNode, int size) {
if (rootNode < size) {
int leftNode = 2 * rootNode + 1;
int rightNode = 2 * rootNode + 2;
int max = rootNode;
if (leftNode < size) {
if (arr[leftNode] > arr[max]) {
max = leftNode;
}
}
if (rightNode < size) {
if (arr[rightNode] > arr[max]) {
max = rightNode;
}
}
if (max != rootNode) {
int tmp = arr[max];
arr[max] = arr[rootNode];
arr[rootNode] = tmp;
buildheap(arr, max, size);
}
}
}
/**merge sort 歸併排序原理(升序):
* 把序列看做對兩個有序隊列的排序,遞歸對兩個序列排序直至隊列只包含兩個元素,然後將兩個有序隊列合併;
* 演算法思想:遞歸加分治
* 時間複雜度:O[NlogN]
* 空間複雜度:O[N]
* 穩定性:穩定
*/
public static void mergeSort(int[] array) {
int length = array.length;
int middle = length / 2;
if (length > 1) {
int[] left = Arrays.copyOfRange(array, 0, middle);// 拷貝數組array的左半部分
int[] right = Arrays.copyOfRange(array, middle, length);// 拷貝數組array的右半部分
mergeSort(left);// 遞歸array的左半部分
mergeSort(right);// 遞歸array的右半部分
merge(array, left, right);// 數組左半部分、右半部分合併到Array
}
}
// 合併數
private static void merge(int[] result, int[] left, int[] right) {
int i = 0, l = 0, r = 0;
while (l < left.length && r < right.length) {
if (left[l] < right[r]) {
result[i] = left[l];
i++;
l++;
} else {
result[i] = right[r];
i++;
r++;
}
}
while (r < right.length) {// 如果右邊剩下合併右邊的
result[i] = right[r];
r++;
i++;
}
while (l < left.length) {
result[i] = left[l];
l++;
i++;
}
}
/**
* radix sort 基數排序原理(升序):
* 桶排序的改進版窗,桶的大小固定為10;
* 首先對數組元素的個位數值大小按桶排序進行排序;接著按元素的十位數值大小按桶排序進行排序;依次按桶排序將最高位排序完成;
* 時間複雜度:O[d(r+N)]
* 空間複雜度:O[rd+N]
* 穩定性:穩定
*/
private static int[] radix(int[] arr) {
if (null == arr || arr.length == 0) {
return null;
}
int[] tmp1 = new int[10];
int[][] tmp2 = new int[10][arr.length];
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (max < arr[i]) {
max = arr[i];
}
}
int num = 1;
while ((max /= 10) > 0) {
num += 1;
}
for (int i = 0; i < num; i++) {
for (int j = 0; j < arr.length; j++) {
int index = arr[j] / ((int) Math.pow(10, i)) % 10;
tmp2[index][tmp1[index]] = arr[j];
tmp1[index] += 1;
}
int k = 0;
for (int j = 0; j < tmp1.length; j++) {
// while(tmp1[j] != 0){
for (int h = 0; h < tmp1[j]; h++) {
arr[k] = tmp2[j][h];
// tmp2[j][h] = 0;
// tmp1[j]--;
k++;
}
tmp1[j] = 0;
// }
}
}
return arr;
}
/**
* bucket sort 桶排序原理(升序):
* 找出序列最大值,創建最大值加一的新數組;
* 遍曆數組,元素值對應新數組下標的位置加一;
* 遍歷新數組,將元素值非0的下標值載入原數組;
* 時間複雜度:O[N]
* 空間複雜度:O[N]
* 穩定性:不穩定
*/
private static int[] bucket(int[] arr) {
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (max < arr[i]) {
max = arr[i];
}
}
int[] tmp = new int[max + 1];
for (int j = 0; j < arr.length; j++) {
tmp[arr[j]] += 1;
}
int k = 0;
for (int i = 0; i < tmp.length; i++) {
while (tmp[i] != 0) {
arr[k] = i;
k++;
tmp[i]--;
}
}
return arr;
}
/**
* shell sort 希爾排序原理(升序):
* 插入排序改進版;
* 把元素分組,每組插入排序 ;
* 改變分組增量,直至增量為1;
* 時間複雜度:O[N^2]
* 空間複雜度:O[1]
* 穩定性:不穩定
*/
private static int[] shell(int[] arr) {
int len = arr.length;
for (int i = len / 2; i > 0; i = i / 2) {// 增量
for (int j = 0; j < i; j++) {// 分組數
for (int k = 1; k < len / i; k++) {// 每組的元素數
int m = k - 1;
for (; m >= 0; m--)
// 逆序,前面部分為有序
if (arr[j + i * k] >= arr[j + i * m])
break;
if (m != k - 1) {
int n = k;
int tmp = arr[j + i * n];
for (; n > m + 1; n--) {
arr[j + i * n] = arr[j + i * (n - 1)];
}
arr[j + i * n] = tmp;
}
}
}
}
return arr;
}
/*
* insert sort 插入排序原理(升序):
* 改原理是將待排序元素插入一個有序隊列,將左邊部分當做一個有序隊列;
* 時間複雜度:O[N^2]
* 空間複雜度:O[1]
* 穩定性:穩定
*/
private static int[] insert(int[] arr) {
for (int i = 1; i < arr.length; ++i) {
/*
* 分為1,2兩部分處理,可以囊括j = beg - 1時的情況 即需要將arr[i]插入到首元素前的位置,若使用一個for
* 包括這兩部分,則會在發生這種情況時退出
*/
/* 1 */
int j = i - 1;
for (; j >= 0; --j)
if (arr[j] <= arr[i])
break;
/* 2 */
if (j != i - 1) {
int temp = arr[i];
for (int k = i; k > j + 1; --k) {
arr[k] = arr[k - 1];
}
arr[j + 1] = temp;
}
}
return arr;
}
/*
* fast sort 快速排序原理(升序):
* 選一基準元素,小於其大小的元素放在左邊,大於它的元素放在右邊;
* 取基準元素的前後兩部分做同樣處理,直至基準元素的兩邊各有一個元素為止;
* 時間複雜度:O[NlogN]
* 空間複雜度:O[NlogN]
* 穩定性:不穩定
*/
private static int[] fast(int[] arr, int begin, int end) {
if (begin >= end) {
return arr;
}
int lindex = begin;
int rindex = end;
int mid = arr[lindex];
while (lindex < rindex) {
while (lindex < rindex) {
if (arr[rindex] < mid) {
arr[lindex++] = arr[rindex];
break;
}
--rindex;
}
while (lindex < rindex) {
if (arr[lindex] >= mid) {
arr[rindex--] = arr[lindex];
break;
}
++lindex;
}
}
arr[lindex] = mid;
fast(arr, begin, lindex);
fast(arr, rindex + 1, end);
return arr;
}
/*
* select sort 選擇排序原理(升序):
* 找出元素最小值放在第一位,接著次小值放在第二位,依次將數組升序排列
* 時間複雜度:O[N^2]
* 空間複雜度:O[1]
* 穩定性:不穩定
*/
private static int[] select(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
for (int j = i + 1; j < arr.length; j++) {
if (arr[j] < arr[i]) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
}
return arr;
}
/*
* bubble sort 冒泡排序原理(升序):
* 依次比較相鄰兩個元素,若後位元素較大則交換至,直至最後一位元素為最大值;
* 接著進行下一輪比較,直至倒數第二位元素為次大值;
* 進行比較至所有元素為升序排列
* 時間複雜度:O[N^2]
* 空間複雜度:O[1]
* 穩定性:不穩定
*/
private static int[] bubble(int[] arr) {
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
return arr;
}
}