【演算法】Java實現七種常用排序演算法
分類
- 插入排序
- 直接插入排序
- 希爾排序
- 交換排序
- 氣泡排序
- 快速排序
- 選擇排序
- 直接選擇排序
- 堆排序
- 歸併排序
- 歸併
- 歸併排序
插入排序
直接插入排序
將待排序陣列看作是左右兩部分,左邊為無序區,右邊為有序區。排序過程就是將右邊無序區中的元素逐個插入到左邊有序區中,最後整個陣列為有序區。
package test;
import java.util.Arrays;
public class Sort {
public static void main(String[] args) {
int[] array = {2, 6, 3, 8, 23, 6, 2, -1, 14, 67, 4, 35, 90};
Sort.directInsert(array);
System.out.println(Arrays.toString(array));
}
public static void directInsert(int[] array) {
int length = array.length;
int i; //當前要排序的元素,初始為第二個元素,預設第一個元素為有序區
int j; //有序區中要比較的元素,比較大小後移動或插入
int temp; //儲存當前要排序的元素,從而空出一個位置用於移動有序區,再將該元素插入有序區的空位
for (i = 1; i < length; i++) {
temp = array[i];
j = i - 1; //空位左邊的第一個元素
// 降序是找到比他大的元素,升序是找到比他小的元素
while (j >= 0 && array[j] > temp) {
array[j + 1] = array[j]; //如果該元素比他大,則將該元素後移,即升序
j--;
}
array[j + 1] = temp; //j+1就是空位
}
}
}
希爾排序
將待排序陣列劃分為若干組,在每組內進行直接插入排序,以使整個序列基本有序,然後再對整個序列進行直接插入排序
public class Sort {
public static void main(String[] args) {
int[] array = {2, 6, 3, 8, 23, 6, 2, -1, 14, 67, 4, 35, 90};
Sort.shell(array);
System.out.println(Arrays.toString(array));
}
public static void shell(int[] array) {
int length = array.length;
int i; //本組中要排序的元素
int j; //本組中空位的前一個元素
int temp; //儲存本組要排序的元素,從而空出一個位置用於移動本組的元素,再將該元素插入本組的空位
int step; //將陣列分為step組,step為相同組的元素的間隔步長
// 初始分組,最終分為一組
step = length / 2;
//step最終為1
while (step != 0) {
//對每組進行直接插入排序,i初始化為每組的第二個元素
for (i = step; i < length; i++) {
temp = array[i]; //留出空位用於移動有序區
j = i - step; //j為本組中空位的前一個元素
while (j >= 0 && array[j] > temp) {
array[j + step] = array[j]; //將大於temp的元素後移,即升序
j -= step; //向本組的有序區左邊移動,j為空位前一個元素
}
array[j + step] = temp; //j+step為空位
}
//進行再次分組
step /= 2;
}
}
}
交換排序
氣泡排序
從一端開始,逐個比較相鄰的兩個元素,發現倒序即交換
public class Sort {
public static void main(String[] args) {
int[] array = {2, 6, 3, 8, 23, 6, 2, -1, 14, 67, 4, 35, 90};
Sort.bubble(array);
System.out.println(Arrays.toString(array));
}
public static void bubble(int[] array) {
int length = array.length;
int i; //泡的位置,即迭代次數,一共要冒length-1個泡,最後一個不用冒
int j; //指向當前正在排序的元素,一直指到上一個泡的下面
int temp; //用於交換位置時騰出空位
//泡依次冒到右邊,即每次都是從無序區選一個最大值冒泡
for (i = (length - 1); i > 0; i--) {
for (j = 0; j < i; j++) {
if (array[j] > array[j + 1]) {
temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
}
}
快速排序
首先選定一個元素作為中間元素,然後將陣列中所有元素與該中間元素比較,將比中間元素小的放在陣列前面,比中間元素大的放在陣列後面,再以中間元素作為分界點,得到左右兩部分陣列,而中間元素位於正確位置上,不用參與後續排序。
然後再對左右兩部分分別進行快速排序,即對得到的兩個子陣列再採用相同的方式來排序和劃分,直到每個子陣列僅有一個元素或為空陣列為止,此時陣列所有元素都有序。
public class Sort {
public static void main(String[] args) {
int[] array = {2, 6, 3, 8, 23, 6, 2, -1, 14, 67, 4, 35, 90};
Sort.quick(array, 0, array.length - 1);
System.out.println(Arrays.toString(array));
}
public static void quick(int[] array, int start, int end) {
int i; //基準左邊的指標,指向正在排序的元素,也指向空位
int j; //基準右邊的指標,指向正在排序的元素,也指向空位
int temp; //用於儲存基準,一般是第一個元素,最後將基準放在中間
if (start < end) {
i = start;
j = end;
temp = array[i];
while (i < j) {
//由於以第一位為基準,空位在左邊,則先從右邊找到小於基準的元素,放在左邊
while (i < j && array[j] > temp) {
j--;
}
if (i < j) {
array[i] = array[j]; //現在j是空位
i++;
}
//從左邊找到大於基準的元素,然後放在右邊的空位
while (i < j && array[i] < temp) {
i++;
}
if (i < j) {
array[j] = array[i]; //現在i是空位
j--;
}
}
//將基準放在空位
array[i] = temp;
//劃分陣列進行遞迴排序,基準不用進行排序
quick(array, start, i - 1);
quick(array, i + 1, end);
}
}
}
選擇排序
直接選擇排序
在每一趟排序中,在待排序陣列中選出最小或最大的元素放在其最終的位置上
public class Sort {
public static void main(String[] args) {
int[] array = {2, 6, 3, 8, 23, 6, 2, -1, 14, 67, 4, 35, 90};
Sort.select(array);
System.out.println(Arrays.toString(array));
}
public static void select(int[] array) {
int length = array.length;
int i; //將要放置正確元素的位置,一共有length-1個,最後一個是正確的
int j; //指向正在排序的元素
int min; //初始化最小值,用於和後面元素比較,找到正確值進行交換位置
int temp; //交換位置時使用
for (i = 0; i < length - 1; i++) {
min = i;
for (j = i + 1; j < length; j++) {
if (array[min] > array[j]) {
min = j; //當前最小值
}
}
//如果最小值不等於最初值,則將換位置
if (min != i) {
temp = array[i];
array[i] = array[min];
array[min] = temp;
}
}
}
}
堆排序
堆排序的原理比之前的排序方法更復雜,這裡就不多說了,已經有很多資料
public class Sort {
public static void main(String[] args) {
int[] array = {2, 6, 3, 8, 23, 6, 2, -1, 14, 67, 4, 35, 90};
Sort.heap(array);
System.out.println(Arrays.toString(array));
}
public static void heap(int[] array) {
int length = array.length;
int temp;
// 建立初始堆
for (int i = (length - 1) / 2; i >= 0; i--) {
sift(array, i, length - 1);
}
System.out.println(Arrays.toString(array));
// 逐步將根結點與末尾元素交換,並調整剩餘陣列為堆,即每次將最大值放在右邊
for (int i = length - 1; i > 0; i--) {
temp = array[0];
array[0] = array[i];
array[i] = temp;
sift(array, 0, i - 1);
System.out.println(Arrays.toString(array));
}
}
// 調整陣列中以k為根的子樹序列為堆,最大下標為m
// 假定左右子樹都是堆
private static void sift(int[] array, int k, int m) {
int i = k; // i表示當前根結點
int j = 2 * i + 1; // j指向當前根結點的左孩子
int temp;
// 保證i不是葉子
while (j <= m) {
// 讓j指向左右孩子的最大者
if (j < m && array[j] < array[j + 1]) {
j += 1;
}
// 如果父結點最大,則建堆結束
if (array[i] >= array[j]) {
break;
} else {
temp = array[i];
array[i] = array[j]; // 大的孩子結點值上移
array[j] = temp; // 父結點下沉
i = j; // i表示新的根結點
j = 2 * i + 1; // j變為當前根結點的左孩子
}
}
}
}
歸併排序
歸併
將多個有序表合併成一個有序表
public class Sort {
public static void main(String[] args) {
int[] A = {0,1,2,3,4,5};
int[] B = {2,4,6,8,10,11};
array = Sort.merge(A, B);
System.out.println(Arrays.toString(array));
}
public static int[] merge(int[] A, int[] B) {
int aLength = A.length;
int bLength = B.length;
int[] C = new int[aLength + bLength];
int a = 0, b = 0, c = 0;
// 先按最短長度合併
while (a < aLength && b < bLength) {
if (A[a] > B[b]) {
C[c++] = B[b++];
} else {
C[c++] = A[a++];
}
}
// 填入剩餘元素
while (a < aLength) {
C[c++] = A[a++];
}
while (b < bLength) {
C[c++] = B[b++];
}
return C;
}
}
歸併排序
將整個表看成n個有序子表,然後兩兩歸併
public class Sort {
public static void main(String[] args) {
int[] array = {2, 6, 3, 8, 23, 6, 2, -1, 14, 67, 4, 35, 90};
Sort.mergeSort(array, 0, array.length - 1);
System.out.println(Arrays.toString(array));
}
public static void mergeSort(int[] array, int low, int high) {
int mid = (low + high) / 2;
if (low < high) {
mergeSort(array, low, mid);
mergeSort(array, mid + 1, high);
merge(array, low, mid, high);
}
}
public static void merge(int[] array, int low, int mid, int high) {
int[] temp = new int[high - low + 1]; // 子陣列的輔助空間
int i = low; // 左指標
int j = mid + 1; // 右指標
int k = 0; // 歸併陣列指標
// 先按最小長度歸併
while (i <= mid && j <= high) {
if (array[i] < array[j]) {
temp[k++] = array[i++];
} else {
temp[k++] = array[j++];
}
}
// 填入剩餘元素
while (i <= mid) {
temp[k++] = array[i++];
}
while (j <= high) {
temp[k++] = array[j++];
}
// 修改原陣列
for (int m = 0; m < temp.length; m++) {
array[low + m] = temp[m];
}
}
}
相關文章
- 用 Java 實現的八種常用排序演算法Java排序演算法
- python實現常用五種排序演算法Python排序演算法
- 幾種常用的排序演算法之JavaScript實現排序演算法JavaScript
- 排序演算法-Java實現快速排序演算法排序演算法Java
- JavaScript實現常用排序演算法JavaScript排序演算法
- 排序演算法Java實現排序演算法Java
- 排序演算法 Java實現排序演算法Java
- 八種常用排序演算法排序演算法
- 幾種排序演算法的原理以及 Java 實現排序演算法Java
- 排序演算法:Java實現希爾排序排序演算法Java
- 幾種常用的排序演算法排序演算法
- php實現4種排序演算法PHP排序演算法
- 一遍記住Java常用的八種排序演算法與程式碼實現Java排序演算法
- C#常用8種排序演算法實現以及原理簡介C#排序演算法
- java氣泡排序演算法實現Java排序演算法
- 九種排序演算法的 JavaScript 實現排序演算法JavaScript
- JavaScript實現的7種排序演算法JavaScript排序演算法
- 【Java筆記】十分鐘搞定常用的八種排序演算法與程式碼實現Java筆記排序演算法
- 面試必備:八種排序演算法原理及Java實現面試排序演算法Java
- 用 Java 實現常見的 8 種內部排序演算法Java排序演算法
- Swift實現八種經典排序演算法Swift排序演算法
- 10大排序演算法——Java實現排序演算法Java
- 簡述幾種常用的排序演算法排序演算法
- Java實現氣泡排序和插入排序演算法Java排序演算法
- 常用排序演算法排序演算法
- 排序演算法(七大經典排序演算法)排序演算法
- python實現常見的五種排序演算法Python排序演算法
- 二十、快速排序演算法——JAVA實現(遞迴)排序演算法Java遞迴
- 【JAVA演算法】排序演算法 -- 快速排序Java演算法排序
- 常用排序演算法之桶排序排序演算法
- 六種排序演算法的JavaScript實現以及總結排序演算法JavaScript
- 快速理解7種排序演算法 | python3實現(排序演算法Python
- 【資料結構】 各種排序演算法的實現資料結構排序演算法
- 如何理解JavaScript中常用的4種排序演算法?JavaScript排序演算法
- Java實現常用加密演算法-SM4Java加密演算法
- 常用的排序演算法(五)--選擇排序以及最佳化(PHP實現)排序演算法PHP
- 排序演算法之快速排序的實現排序演算法
- 7種排序演算法排序演算法