1. 程式人生 > >用java語言實現七大排序演算法

用java語言實現七大排序演算法

自定義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;
    }
}