八大排序算法-Java實現
1. 插入排序
2. 希爾排序
3. 選擇排序
4. 堆排序
5. 冒泡排序
6. 快速排序
7. 歸併排序
8. 基數排序
插入排序
代碼實現:
//通過冒泡的方法進行插入排序
public static void sort(int[] a){
for(int i = 0; i< a.length -1; i++){
for(int j = i + 1; j>0; j--){
if(a[j]<a[j-1]){
int temp = a[j];
a[j] = a[j-1];
a[j-1] = temp;
}
}
}
}
//通過將較大的元素都向右移動而不總是交換兩個元素
//此方法優於前者
public static void sort(int[] a){
for(int i = 1; i< a.length; i++){
int num = a[i];
int j;
for(j = i ; j>0 && num < a[j-1]; j--){
a[j] = a[j-1];
}
a[j] = num;
}
}
希爾排序
希爾排序,也稱爲遞減增量排序算法,是插入排序的一種更加高效的改進版本。(非穩定排序算法)
- 插入排序在對幾乎已經排好序的數據進行操作的時候,效率高,可以達到現行排序的效率。
- 一般來說比較低效,因爲插入排序每次只能將數據移動一格。
代碼實現:
```java public static void sort(int[] a) { int length = a.length; int h = 1; while (h < length / 3) h = 3 * h + 1; for (; h >= 1; h /= 3) { for (int i = 0; i < a.length - h; i += h) { for (int j = i + h; j > 0; j -= h) { if (a[j] < a[j - h]) { int temp = a[j]; a[j] = a[j - h]; a[j - h] = temp; } } } } } ```選擇排序
選擇排序(Selection sort)是一種簡單直觀的排序算法。它的工作原理如下。首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然後,再從剩餘未排序元素中繼續尋找最小(大)元素,然後放到已排序序列的末尾。以此類推,直到所有元素均排序完畢。
代碼實現:
public static void sort(int[] a) {
for (int i = 0; i < a.length; i++) {
int min = i;
//選出之後待排序中值最小的位置
for (int j = i + 1; j < a.length; j++) {
if (a[j] < a[min]) {
min = j;
}
}
//最小值不等於當前值時進行交換
if (min != i) {
int temp = a[i];
a[i] = a[min];
a[min] = temp;
}
}
}
堆排序
代碼實現:
(沒看懂!)以後有時間再看看。
public static void sort(int[] a) {
for (int i = a.length - 1; i > 0; i--) {
max_heapify(a, i);
//堆頂元素(第一個元素)與Kn交換
int temp = a[0];
a[0] = a[i];
a[i] = temp;
}
}
/***
*
* 將數組堆化
* i = 第一個非葉子節點。
* 從第一個非葉子節點開始即可。無需從最後一個葉子節點開始。
* 葉子節點可以看作已符合堆要求的節點,根節點就是它自己且自己以下值爲最大。
*/
public static void max_heapify(int[] a, int n) {
int child;
for (int i = (n - 1) / 2; i >= 0; i--) {
//左子節點位置
child = 2 * i + 1;
//右子節點存在且大於左子節點,child變成右子節點
if (child != n && a[child] < a[child + 1]) {
child++;
}
//交換父節點與左右子節點中的最大值
if (a[i] < a[child]) {
int temp = a[i];
a[i] = a[child];
a[child] = temp;
}
}
}
冒泡排序
代碼實現:
public static void sort(int[] a) {
//外層循環控制比較的次數
for (int i = 0; i < a.length - 1; i++) {
//內層循環控制到達位置
for (int j = 0; j < a.length - i - 1; j++) {
//前面的元素比後面大就交換
if (a[j] > a[j + 1]) {
int temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
}
快速排序
代碼實現:
快速排序的基本思想: 挖坑填數 + 分治法
快速排序使用分支發策略來把一個串行(list)分爲兩個子串行。
它是處理數據最快的排序算法之一。
代碼實現:
public static void sort(int[] a, int low, int high) {
//已經排完
if (low >= high) {
return;
}
int left = low;
int right = high;
//保存基準值
int pivot = a[left];
while (left < right) {
//從後向前找到比基準小的元素
while (left < right && a[right] >= pivot)
right--;
a[left] = a[right];
//從前往後找到比基準大的元素
while (left < right && a[left] <= pivot)
left++;
a[right] = a[left];
}
// 放置基準值,準備分治遞歸快排
a[left] = pivot;
sort(a, low, left - 1);
sort(a, left + 1, high);
}
歸併排序
代碼實現:
歸併排序是建立在歸併操作上的一種有效的排序算法。是一個採用分治法的一個非常典型的應用,且各層分治遞歸可以同時進行。
public class Merge {
//歸併所需的輔助數組
private static int[] aux;
public static void sort(int[] a) {
//一次性分配空間
aux = new int[a.length];
sort(a, 0, a.length - 1);
}
public static void sort(int[] a, int low, int high) {
if (low >= high) {
return;
}
int mid = (low + high) / 2;
//將左半邊排序
sort(a, low, mid);
//將右半邊排序
sort(a, mid + 1, high);
merge(a, low, mid, high);
}
/**
* 該方法先將所有元素複製到aux[]中,然後在歸併會a[]中。方法咋歸併時(第二個for循環)
* 進行了4個條件判斷:
* - 左半邊用盡(取右半邊的元素)
* - 右半邊用盡(取左半邊的元素)
* - 右半邊的當前元素小於左半邊的當前元素(取右半邊的元素)
* - 右半邊的當前元素大於等於左半邊的當前元素(取左半邊的元素)
*/
public static void merge(int[] a, int low, int mid, int high) {
//將a[low..mid]和a[mid+1..high]歸併
int i = low, j = mid + 1;
for (int k = low; k <= high; k++) {
aux[k] = a[k];
}
for (int k = low; k <= high; k++) {
if (i > mid) {
a[k] = aux[j++];
} else if (j > high) {
a[k] = aux[i++];
} else if (aux[j] < aux[i]) {
a[k] = aux[j++];
} else {
a[k] = aux[i++];
}
}
}
}
基數排序
代碼實現:
public static void sort(int[] arr) {
if (arr.length <= 1) return;
//取得數組中的最大數,並取得位數
int max = 0;
for (int i = 0; i < arr.length; i++) {
if (max < arr[i]) {
max = arr[i];
}
}
int maxDigit = 1;
while (max / 10 > 0) {
maxDigit++;
max = max / 10;
}
//申請一個桶空間
int[][] buckets = new int[10][arr.length];
int base = 10;
//從低位到高位,對每一位遍歷,將所有元素分配到桶中
for (int i = 0; i < maxDigit; i++) {
int[] bktLen = new int[10]; //存儲各個桶中存儲元素的數量
//分配:將所有元素分配到桶中
for (int j = 0; j < arr.length; j++) {
int whichBucket = (arr[j] % base) / (base / 10);
buckets[whichBucket][bktLen[whichBucket]] = arr[j];
bktLen[whichBucket]++;
}
//收集:將不同桶裏數據挨個撈出來,爲下一輪高位排序做準備,由於靠近桶底的元素排名靠前,因此從桶底先撈
int k = 0;
for (int b = 0; b < buckets.length; b++) {
for (int p = 0; p < bktLen[b]; p++) {
arr[k++] = buckets[b][p];
}
}
base *= 10;
}
}