[Java]各種基礎的查找和排序算法總結

查找方法:
1.順序查找。
按數組的順序從前往後一直比較,直到找到目標值返回。
優點:對數組的結構沒有特定的要求,算法簡單。
缺點:當數組個數n較大時,效率低下。
時間複雜度:最大時間複雜度是O(n),最小時間複雜度是O(1),平均時間複雜度是O(n/2).


<span style="white-space:pre">	</span>/**
	 * 順序查找算法
	 * 
	 * @param array
	 *            數組
	 * @param target
	 *            目標
	 * @return 找到,返回下標值;找不到返回0x80000000
	 */
	public int sequentialSearch(int[] array, int target) {
		if (array == null) {
			throw new NullPointerException("the array can't not be null!");
		}
		if (array.length <= 0) {
			throw new IllegalArgumentException("the length of array is illgal!");
		}
		for (int index = 0; index < array.length - 1; index++) {
			if (array[index] == target) {
				return index;
			}
		}
		return Integer.MIN_VALUE;
	}


2.二分查找:
從數組的中間開始查找,若找到目標值則返回;若目標值比中間數小則遞歸查找前半部分;若目標值比中間數大則遞歸查找後半部分。
優點:比較次數較少,效率比較高
缺點:只適用於不經常變動有序數組

時間複雜度:O(log(n))

	/**
	 * 二分查找算法 
	 * @param array 有序數組
	 * @param target 目標數值
	 * @return 找到,返回下標值;找不到返回0x80000000
	 */
	public int binarySearch(int[] array, int target) {
		if (array == null) {
			throw new NullPointerException("the array can't not be null!");
		}
		if (array.length <= 0) {
			throw new IllegalArgumentException("the length of array is illgal!");
		}
		int low = 0;
		int high = array.length - 1;
		while (low <= high) {
			int middle = (low + high) / 2;
			if (target == array[middle]) {
				return middle;
			}
			if (target > array[middle]) {
				low = middle + 1;
			} else {
				high = middle - 1;
			}
		}
		return Integer.MIN_VALUE;
	}




排序方法:
1.插入排序:
將一個數據插入到已經排好序的有序數據中,在有序序列中選出合適的位置插入,從而得到一個新的、個數加一的有序數據。

優點:是穩定的排序方法。
缺點:算法適用於少量數據的排序

時間複雜度爲O(n^2)。


<span style="white-space:pre">	</span>public int[] insertSort(int[] array) {
		if (array == null) {
			throw new NullPointerException("the array can't not be null!");
		}
		if (array.length <= 0) {
			throw new IllegalArgumentException("the length of array is illgal!");
		}
		for (int i = 0; i < array.length - 1; i++) {
			int index = halfFindIndex(array, array[i], i);
			if (index != i) {
				int temp = array[i];
				for (int j = i; j > index; j--) {
					array[j] = array[j - 1];
				}
				array[index] = temp;
			}
		}
		return array;
	}

	private int halfFindIndex(int[] array, int target, int end) {
		int low = 0;
		int high = end;
		int middle = 0;
		while (low <= high) {
			middle = (low + high) / 2;
			if (target < array[middle]) {
				low = middle + 1;
			} else {
				high = middle - 1;
			}
		}
		if (target > array[middle]) {
			middle++;
		}
		return middle;
	}



2.冒泡排序
每次將相鄰的兩個數進行比較,如果想升序,則大數往後,反之亦然。

優點:算法簡單,穩定算法
缺點:效率低下的排序方法,在數據規模很小時,可以採用;

時間複雜度:無序O(n^2),有序o(1)
<span style="white-space:pre">	</span>public int[] bubbleSort(int[] array) {
		if (array == null) {
			throw new NullPointerException("the array can't not be null!");
		}
		if (array.length <= 0) {
			throw new IllegalArgumentException("the length of array is illgal!");
		}
		int flag = array.length - 1;
		while (flag > 0) {
			int end = flag;
			flag = 0;
			for (int i = 0; i < end; i++) {
				if (array[i] > array[i + 1]) {
					int temp = array[i + 1];
					array[i + 1] = array[i];
					array[i] = temp;
					flag = i;
				}
			}
		}
		return array;
	}




3.歸併排序
採用分治的思想,通過分割和合並,達到目的

優點:算法簡單,穩定算法

平均時間複雜度:O(nlog2n)

空間複雜度:O(n)  (用於存儲有序子序列合併後有序序列)


	/**
	 * 歸併排序
	 * 
	 * @param unSortArray
	 * @return
	 * @throws NullPointerException
	 * @throws IllegalArgumentException
	 */
	public int[] mergerSort(int[] unSortArray) throws NullPointerException,
			IllegalArgumentException {
		if (unSortArray == null) {
			throw new NullPointerException("the array is null!");
		}
		if (unSortArray.length <= 0) {
			throw new IllegalArgumentException("the size of array is illgal!");
		}
		int last = unSortArray.length - 1;
		int[] temp = new int[unSortArray.length];
		return merger(unSortArray, 0, last, temp);
	}

	/**
	 * 遞歸實現歸併排序
	 * 
	 * @param unSortArray
	 *            無序數組
	 * @param first
	 *            開始下標
	 * @param last
	 *            最後有效下標
	 */
	private int[] merger(int[] unSortArray, int first, int last, int[] temp) {
		if (temp == null) {
			return null;
		}
		if (first < last) {
			int middle = (first + last) / 2;
			// 左邊
			merger(unSortArray, first, middle, temp);
			// 右邊
			merger(unSortArray, middle + 1, last, temp);
			// 排序
			mergerArray(unSortArray, first, middle, last, temp);
		}
		return unSortArray;
	}

	/**
	 * 將兩個有序序列合併成一個有序序列
	 * 
	 * @param array
	 *            一個無序序列
	 * @param first
	 *            開始的座標
	 * @param last
	 *            最後的座標
	 * @param temp
	 *            暫存數組
	 */
	private void mergerArray(int[] array, int first, int mid, int last,
			int[] temp) {
		int start = first;
		int latterIndex = mid + 1;
		int tempIndex = 0;

		while (start <= mid && latterIndex <= last) {
			// 比較將數放進暫存數組中
			if (array[start] < array[latterIndex]) {
				temp[tempIndex++] = array[start++];
			} else {
				temp[tempIndex++] = array[latterIndex++];
			}
		}
		while (start <= mid) {
			// 將middle以前的有序序列暫存到數組中
			temp[tempIndex++] = array[start++];
		}
		while (latterIndex <= last) {
			// 將middle以後的有序序列暫存到數組中
			temp[tempIndex++] = array[latterIndex++];
		}

		for (int i = 0; i < tempIndex; i++) {
			// 將暫存數組裏的數複製到一開始的無序序列中
			array[first + i] = temp[i];
		}
	}



4.快速排序
1.先從數列中取出一個數作爲基準數。


2.分區過程,將比這個數大的數全放到它的右邊,小於或等於它的數全放到它的左邊。


3.再對左右區間重複第二步,直到各區間只有一個數。
是不穩定的算法


快速排序時間複雜度下界爲O(nlgn),最壞情況爲O(n^2)。在實際應用中,快速排序的平均時間複雜度爲O(nlgn)


只要對快速排序做簡單的操作,就能使時間複雜度總是O(nlgn):

1.對排序數據進行打亂;

2.隨機挑選基準數.



額外空間O(log(n))

<span style="white-space:pre">	</span>public int[] quickSort(int[] unSortArray, int left, int right)
			throws NullPointerException, IllegalArgumentException {
		if (unSortArray == null) {
			throw new NullPointerException("the array is null!");
		}
		if (unSortArray.length <= 0) {
			throw new IllegalArgumentException("the size of array is illgal!");
		}
		if (left < right) {
			int start = left;
			int end = right;
			// 選第一個爲基準
			int x = unSortArray[start];
			while (start < end) {
				while (start < end && x < unSortArray[end]) {
					// 找到小於基準的數
					end--;
				}
				if (start < end) {
					// 交換位置
					unSortArray[start] = unSortArray[end];
					start++;
				}
				while (start < end && x > unSortArray[start]) {
					// 找到大於基準的數
					start++;
				}
				if (start < end) {
					// 交換位置
					unSortArray[end] = unSortArray[start];
					end--;
				}
			}
			unSortArray[start] = x;
			quickSort(unSortArray, left, start - 1); // 遞歸調用
			quickSort(unSortArray, start + 1, right);
		}
		return unSortArray;
	}





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