JAVA代碼實現冒泡、選擇、插入、希爾排序

冒泡、選擇、插入、希爾排序

今天學習了八大算法中的冒泡、選擇、插入、希爾排序算法。以數據從小到大排序爲例,談一談自己的理解。有錯誤之處,還望指出,我會及時改正。

1. 冒泡排序
冒泡排序每次將相鄰元素進行比較,較大的數放在後面,每輪下來,最大的數都會被交換到最後,並且下一輪不需要進行排序了。通過雙重for循環實現,平均和最差時間複雜度爲O(n^2)。

package com.sort.bubbleSort;

import java.util.Arrays;

/*
 * 冒泡排序
 */
public class BubbleSortDemo2 {

	public static void main(String[] args) {
		int[] array = { 5, 9, 8, 3, 2, 0, 1 };
		System.out.println("排序前:" + Arrays.toString(array));
		bubbleSort(array);
		System.out.println("排序後:" + Arrays.toString(array));

	}

	// 冒泡排序
	public static void bubbleSort(int[] array) {
		int temp = 0;
		boolean flag = false;
		// 共執行array.length-1
		for (int i = 0; i < array.length - 1; i++) {
			// 每輪都會將最大的數放到最後,所以每輪只需要執行array.length-1-i次
			for (int j = 0; j < array.length - 1 - i; j++) {
				if (array[j] > array[j + 1]) {
					flag = true;
					temp = array[j + 1];
					array[j + 1] = array[j];
					array[j] = temp;
				}
			}

			// 每輪排序完,檢查一下該輪是否有數調整位置了
			if (!flag) {// 如果沒有數調整位置,說明已經有序了
				break;
			} else {
				flag = false;
			}
		}
	}

}

2. 選擇排序
每輪將最小的數放在前面,直至放完。平均和最差時間複雜度爲O(n^2)。

package com.sort.selectionSort;

import java.util.Arrays;

/*
 * 選擇排序
 */
public class SelectSortDemo2 {

	public static void main(String[] args) {
		int[] array = { 5, 9, 8, 3, 2, 0, 1 };
		System.out.println("排序前:" + Arrays.toString(array));
		selectSort(array);
		System.out.println("排序後:" + Arrays.toString(array));

	}

	// 選擇排序
	public static void selectSort(int[] array) {
		int min = 0;// 記錄最小值
		int minIndex = 0;// 記錄最小值的下標
		// 一共需要排序array.length-1輪
		for (int i = 0; i < array.length - 1; i++) {
			// 假定每輪的第一個數就是最小值
			min = array[i];
			minIndex = i;
			// 每輪會將最小的值放在最前面,所以每輪從第i+1個數開始
			for (int j = i + 1; j < array.length; j++) {
				if (min > array[j]) {// 說明假定的最小值並不是真正的最小值
					// 將更小的那個值標記爲最小值
					min = array[j];
					minIndex = j;
				}
			}
			// 每輪找到最小值後,將最小值和開始假定的最小值交換位置
			if (minIndex != i) {
				array[minIndex] = array[i];
				array[i] = min;
			}
		}
	}

}


3. 插入排序
插入排序的思想是將一堆數分成有序表和無序表兩類,每輪從無序表中取一個數按順序放到有序表中,直至放完。平均和最差時間複雜度爲O(n^2)。

package com.sort.insertSort;

import java.util.Arrays;

/*
 * 插入排序
 */
public class InsertSortDemo2 {

	public static void main(String[] args) {
		int[] array = { 5, 9, 8, 3, 2, 0, 1 };
		System.out.println("排序前:" + Arrays.toString(array));
		insertSort(array);
		System.out.println("排序後:" + Arrays.toString(array));

	}

	// 插入排序
	/*
	 *  思路分析:
	 *    1.插入排序的思想是將一堆數分成有序和無序兩部分,每次從無序組的中取一個數核有序組進行比較,放入有序組
	 *    2.將array數組的第一個數看作一個有序組,後面的n-1個數看作無序組;
	 *    3.從第2個數開始,每取一個數就按順序插入到有序組中
	 *    4.記錄每次待插入的數,記錄每次待插入數前面的那個數的下標
	 *    5.以從小到大排序爲例,那麼每次待插入數的前一個數,即有序組的最後一個數,這個數肯定是最大的,
	 *      如果待插入的數小於這個最大數,說明位置沒找到插入位置,就需要跟最大數前面那個數進行比較,以此類推(下標往前移動)
	 *      直到待插入的數比有序組中某個數大時,插入位置就找到了,就是那個數的位置
	 *    6.交換位置即可
	 *    舉例:{101, 34, 119, 1,-1,89}==>34  {101, 101, 119, 1,-1,89}==>{34, 101, 119, 1,-1,89}
	 *        {34, 101, 119, 1,-1,89}==>119 {34, 101, 119, 1,-1,89}==>{34, 101, 119, 1,-1,89}
	 *        {34, 101, 119, 1,-1,89}==>1 {34, 101, 119, 119,-1,89}==>{34, 101, 101, 119,-1,89}==>{34, 34, 101, 119,-1,89}==>{1, 34, 101, 119,-1,89}
	 */
	public static void insertSort(int[] array) {
		// 先將array中的第一個元素設爲有序表,後面n-1個元素爲無序表,接下來每次從無序表中取一個數據插入到有序表中,所以需要array.length-1輪
		int insertVal = 0;// 待插入的數
		int insertIndex = 0;// 待插入的位置
		for (int i = 1; i < array.length; i++) {
			// 每次從無序表中取第一個數作爲待插入數
			insertVal = array[i];
			// 將待插入數的前一個位置記錄下來,也就是有序表中最大數的位置
			insertIndex = i - 1;
			// 從有序表中最大數的位置開始找,如果待插入的數小於這個最大數,就找打插入位置了,否則,往前移動(將這個最大的數賦值給後一個數),直到遍歷到有序表中的第一個數,也就是最小的那個數爲止
			while (insertIndex >= 0 && insertVal < array[insertIndex]) {
				array[insertIndex + 1] = array[insertIndex];
				insertIndex--;
			}
			// 遍歷結束,說明找到待插入數的位置了
			if (insertIndex + 1 != i) {// 待插入位置就是自己目前的位置就不用移動(裏面就一行代碼,對性能幾乎沒有提升,也可以不做判斷)
				array[insertIndex + 1] = insertVal;
			}
			System.out.println("第" + i + "輪排序" + Arrays.toString(array));
		}
	}

}

4. 希爾排序
希爾排序是一種改進的插入排序。當較小的數比較靠後時,如果使用直接插入排序會移動很多數,這樣導致性能很低,希爾排序通過設定步長進行分組排序的方式,提高了較小數靠後時排序的性能。其平均時間複雜度爲O(nlogn),最壞時間複雜度爲O(n^2)。其方式有兩種,一是交換法,二是移動法。

package com.sort.shellSort;

import java.util.Arrays;

/*
 * 希爾排序
 */
public class ShellSortDemo2 {

	public static void main(String[] args) {
		int[] array = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
		System.out.println("排序前:" + Arrays.toString(array));
		shellSort2(array);
		System.out.println("排序後:" + Arrays.toString(array));

	}

	// 希爾排序(交換法)---不提倡,交換數據對性能有影響
	public static void shellSort1(int[] array) {
		int temp = 0;
		int count = 0;
		// 計算每輪的步長,,每輪的步長也是每輪的組數
		for (int gap = array.length / 2; gap > 0; gap /= 2) {
			// 每輪有gap組,每組的第一個數作爲有序表,不參與排序,所以每輪需要排 array.length-gap次
			for (int i = gap; i < array.length; i++) {
				// 每組的數間隔爲gap
				for (int j = i - gap; j >= 0; j -= gap) {
					if (array[j] > array[j + gap]) {
						temp = array[j + gap];
						array[j + gap] = array[j];
						array[j] = temp;
					}
				}
			}
			System.out.println("第" + (++count) + "輪排序:" + Arrays.toString(array));
		}
	}

	// 希爾排序(移動法)---推薦
	public static void shellSort2(int[] array) {
		int count = 0;
		int insertVal = 0;// 待插入的數
		int insertIndex = 0;// 待插入數的前gap個數的下標
		// 計算每輪的步長,,每輪的步長也是每輪的組數
		for (int gap = array.length / 2; gap > 0; gap /= 2) {
			// 每輪有gap組,每組的第一個數作爲有序表,不參與排序,所以每輪需要排 array.length-gap次
			for (int i = gap; i < array.length; i++) {
				// 先記錄待插入的數
				insertVal = array[i];
				// 記錄待插入數的前gap個數的下標
				insertIndex = i - gap;
				// 對比插入排序:如果前gap個數的下標不在數組的最前面,並且待插入的數小於前gap個數,那就將前gap個數的值賦給當前下標往前移動gap個之後,再比較
				while (insertIndex >= 0 && insertVal < array[insertIndex]) {
					array[insertIndex + gap] = array[insertIndex];
					insertIndex -= gap;
				}
				// 循環結束表示找到插入位置了,就將待插入的數插入到插入位置即可
				if (insertIndex + gap != i) {
					array[insertIndex + gap] = insertVal;
				}
			}
			System.out.println("第" + (++count) + "輪排序:" + Arrays.toString(array));
		}
	}
}

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