用java語言實現七大排序演算法
阿新 • • 發佈:2019-08-10
自定義Sort介面
- Sort介面為以下排序演算法提供比較大小和元素的位置交換。
public abstract class Sort<T extends Comparable<T>> { public abstract void sort(T[] nums); protected boolean less(T v, T w) { return v.compareTo(w) < 0; } protected void swap(T[] a, int i, int j) { T t = a[i]; a[i] = a[j]; a[j] = t; } }
1.選擇排序
- 找出陣列最小的元素放在第一個位置。接著,找出陣列中剩餘的元素中最小的元素放在第二個位置,直到遍歷完這個陣列。
public class Selection<T extends Comparable<T>> extends Sort<T> { @Override public void sort(T[] nums) { int N = nums.length; for (int i = 0; i < N - 1; i++) { int min = i; for (int j = i + 1; j < N; j++) { if (less(nums[j], nums[min])) { min = j; } } swap(nums, i, min); } } }
2.氣泡排序
- 從左往右不斷交換逆序的元素,經過一輪迴圈,最大的元素浮到最後側,在過程中至少有一個元素的最終位置已經確定好。
public class Bubble<T extends Comparable<T>> extends Sort<T> { @Override public void sort(T[] nums) { int N = nums.length; for (int i = 1; i < N; i++) { for (int j = 0; j < nums.length - i; j++) { if(less(nums[j+1], nums[j])) swap(nums, j+1, j); } } } }
3.插入排序
每次都把當前元素插入左側已經排好序的資料,直到所有的元素都插入左側,就完成了對該陣列的排序。
public class Insertion<T extends Comparable<T>> extends Sort<T> {
@Override
public void sort(T[] nums) {
// TODO Auto-generated method stub
int n = nums.length;
for (int i = 1; i < nums.length; i++) {
T val = nums[i];
int j = 0;
for (j = i - 1; j >= 0; j--) {
if (less(val, nums[j]))
nums[j + 1] = nums[j];
else
break;
}
nums[j + 1] = val;
}
}
}
4.希爾排序
- 希爾排序使用插入排序對間隔 h 的序列進行排序。通過不斷減小 h,最後令 h=1,就可以使得整個陣列是有序的
public class Shell <T extends Comparable<T>> extends Sort<T> {
@Override
public void sort(T[] nums) {
int N = nums.length;
int h = 1;
while (h < N / 3) {
h = 3 * h + 1; // 1, 4, 13, 40, ...
}
while (h >= 1) {
for (int i = h; i < N; i++) {
for (int j = i; j >= h && less(nums[j], nums[j - h]); j = j - h) {
swap(nums, j, j - h);
}
}
h = h / 3;
}
}
}
5.歸併排序
- 以下程式碼使用自頂向下歸併排序,使用分治演算法實現,把大問題分對半分成兩個小問題,時間複雜度一般為O(nlogn)
- merge方法對兩個子陣列進行歸併,通過把原有的資料複製到輔助資料中,對比輔助中的兩個子陣列依次按順序排入原有陣列。
public class MergeSort<T extends Comparable<T>> extends Sort<T> {
protected T[] aux;
public void merge(T[] nums, int l, int m, int h) {
int i = l, j = m + 1;
for (int k = l; k <= h; k++) {
aux[k] = nums[k];
}
for (int k = l; k <= h; k++) {
if (j > h)
nums[k] = aux[i++];
else if (i > m)
nums[k] = aux[j++];
else if (aux[i].compareTo(aux[j]) <= 0)
nums[k] = aux[i++];
else
nums[k] = aux[j++];
}
}
@Override
public void sort(T[] nums) {
aux = (T[]) new Comparable[nums.length];
sort(nums, 0, nums.length - 1);
}
public void sort(T[] nums, int l, int h) {
if (h <= l)
return;
int m = l + (h - l) / 2;
sort(nums, l, m);
sort(nums, m + 1, h);
merge(nums, l, m, h);
}
}
6.快速排序
- 以切分為基準分成兩個子陣列,左子陣列小於切分元素,右子陣列大於切分元素。當兩個子陣列排好序時整個陣列就排好序了。
- partition方法:
- 取nums[l]為切分元素,從左往右掃描直到找到一個大於它的元素,再從右往左掃描找到一個小於它的元素,交換這兩個元素的位置。
- 不斷進行這個過程,直到指標i左側元素<切分元素,指標j右側元素大於切分元素。當兩個指標相遇時,交換指標i和指標j的位置。
public class QuickSort<T extends Comparable<T>> extends Sort<T> {
private int partition(T[] nums, int l, int h) {
int i = l, j = h + 1;
T v = nums[l];
while (true) {
while (less(nums[++i], v) && i != h);
while (less(v, nums[--j]) && j != l);
if (i >= j)
break;
swap(nums, i, j);
}
swap(nums, l, j);
return j;
}
@Override
public void sort(T[] nums) {
// TODO Auto-generated method stub
shuffle(nums);
sort(nums, 0, nums.length - 1);
}
public void sort(T[] nums, int l, int h) {
if (h <= l)
return;
int j = partition(nums, l, h);
sort(nums, l, j - 1);
sort(nums, j + 1, h);
}
private void shuffle(T[] nums) {
List<Comparable> list = Arrays.asList(nums);
Collections.shuffle(list);
list.toArray(nums);
}
}
7.堆排序
- sort():堆的構建,從右往左進行下沉操作。不斷用堆頂的元素與陣列的最後一個元素交換,同時堆的大小不斷減一,直到堆的大小為1,陣列就排好序了。
public class HeapSort <T extends Comparable<T>> extends Sort<T> {
@Override
public void sort(T[] nums) {
int N = nums.length - 1;
for (int k = N / 2; k >= 1; k--) {
sink(nums,k,N);
}
while(N > 1) {
swap(nums, 1, N--);
sink(nums,1,N);
}
}
private void sink(T[] nums, int k, int N) {
while(2 * k <= N){
int j = 2 * k;
if(j < N && less(nums,j,j+1))
j++;
if(!less(nums,k,j))
break;
swap(nums, k, j);
k = j;
}
}
private boolean less(T[] nums, int i, int j) {
return nums[i].compareTo(nums[j]) < 0;
}
}