最壞情況線性時間的選擇 java實現

package ctgu.sugite.content.character09;

import java.util.Arrays;
import java.util.Random;

public class WorstLinearSelect {

	public static void main(String[] args) {
		int n = 34, k = 7;/* 34個元素中找出第7小的元素 */
		int[] a = new int[n];
		Random rd = new Random();
		for (int i = 0; i < n; i++) {
			a[i] = rd.nextInt(100);
		}
		System.out.println(Arrays.toString(a));
		System.out.println(select(a, 0, n - 1, k));/* 進行線性查找 */
		Arrays.sort(a);
		System.out.println(Arrays.toString(a));/* 排序後輸出,進行驗證 */
	}

	private static int select(int[] a, int law, int high, int k) {
		if (high - law < 5) {
			insertSort(a, law, high);
			return a[law + k - 1];
		}
		int teams = (high - law + 5) / 5;// 組數
		for (int i = 0; i < teams; i++) {
			/* 第一步:將輸入數組的n個元素劃分爲n/5組,每組5個元素,且至多隻有一個組由剩下的n mod5個元素組成 */
			int left = law + i * 5;
			int right = (law + i * 5 + 4) > high ? high : law + i * 5 + 4;
			int mid = (left + right) / 2;
			/* 第二步:尋找(n+4)/5個組中每一組的中位數。首先對每組中的元素(至多爲5個)進行插入排序,然後從排序過的序列中選出中位數 */
			insertSort(a, left, right);
			swap(a, law + i, mid);// 將中位數置前
		}
		/* 第三步:對第二步中找出的(n+4)/5箇中位數,遞歸調用select以找出其中位數x */
		int pivot = select(a, law, law + teams - 1, (teams + 1) / 2);
		/* 第四步:利用修改過的partition過程,按中位數的中位數x對輸入數組進行劃分 */
		int pos = partition(a, law, high, pivot);
		/* 第五步:判斷pos位置是否爲要找的數,若不是則在低區或者高區遞歸select */
		int leftNum = pos - law;
		if (k == leftNum + 1)
			return a[pos];
		else if (k <= leftNum)
			return select(a, law, pos - 1, k);
		else
			return select(a, pos + 1, high, k - leftNum - 1);
	}

	private static int partition(int[] a, int law, int high, int pivot) {
		int index = law;
		for (int i = law; i <= high; i++) {
			if (a[i] == pivot) {
				index = i;
				break;
			}
		}/* 找到樞紐的位置 */
		swap(a, index, high);
		int i = law - 1;
		for (int j = law; j < high; j++) {
			if (a[j] <= pivot) {
				swap(a, j, ++i);
			}
		}
		swap(a, high, ++i);
		return i;
	}

	private static void swap(int[] a, int i, int j) {
		int temp = a[i];
		a[i] = a[j];
		a[j] = temp;
	}

	/* 插入排序 */
	private static void insertSort(int[] a, int law, int high) {
		for (int i = law + 1; i <= high; i++) {
			int key = a[i];
			int j = i - 1;
			while (j >= law && a[j] > key) {
				a[j + 1] = a[j];
				j--;
			}
			a[j + 1] = key;
		}
	}
}

形象的執行過程可以看看這個:

http://resource.jingpinke.com/details?uuid=ff808081-22e8911b-0122-e8912643-048d&objectId=oid:ff808081-22e8911b-0122-e8912643-048e

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章