數據結構Java03【算法(時間複雜度、空間複雜度),排序(冒泡、快速、插入、希爾、選擇、歸併、基數、隊列基數)】

目   錄

P19-3.1算法的時間複雜度和空間複雜度

1、時間複雜度

1.1、忽略常數

1.2、忽略低次項

1.3、忽略係數

2、衡量一個算法的優劣(時間複雜度、空間複雜度)

2.1、語句頻度T(n)

2.2、時間複雜度

2.3、常見的時間複雜度

2.4、時間複雜度

2.5、平均時間複雜度和最壞時間複雜度

P20-3.2排序算法之冒泡排序

P21-3.3排序算法之快速排序

P22-3.4排序算法之插入排序

P23-3.5排序算法之希爾排序

P24-3.6排序算法之選擇排序

P25-3.7排序算法之歸併排序

P26-3.8排序算法之基數排序

P27-3.9基數排序之隊列實現


P19-3.1算法的時間複雜度和空間複雜度

1、時間複雜度

1.1、忽略常數

1.2、忽略低次項

1.3、忽略係數

2、衡量一個算法的優劣(時間複雜度、空間複雜度)

一、事後統計的方法

二、事前分析估算的方法

 

計算1-100所有數字之和

2.1、語句頻度T(n)

一個算法中的語句執行次數稱爲語句頻度,記爲T(n)。

2.2、時間複雜度

 一般情況下,算法中的基本操作語句的重複執行次數是問題規模n的某個函數,用T(n)表示,若有某個輔助函數f(n),使得當n趨近於無窮大時,T(n) / f(n) 的極限值爲不等於零的常數,則稱f(n)T(n)的同數量級函數。記作 T(n)=( f(n) ),稱O( f(n) )  爲算法的漸進時間複雜度,簡稱時間複雜度。

T(n) 不同,但時間複雜度可能相同。 如:T(n)=n²+5n+6 T(n)=3n²+3n+2 它們的T(n) 不同,但時間複雜度相同,都爲O(n²)。

2.3、常見的時間複雜度

常數階O(1)

對數階O(log2n)

線性階O(n)

線性對數階O(nlog2n)

平方階O(n2)

立方階O(n3)

k次方階O(nk)

指數階O(2n)

隨着問題規模n的不斷增大,上述時間複雜度不斷增大,算法的執行效率越低。

2.4、時間複雜度

計算時間複雜度的方法:

用常數1代替運行時間中的所有加法常數 

修改後的運行次數函數中,只保留最高階項 

去除最高階項的係數

2.5、平均時間複雜度和最壞時間複雜度

平均時間複雜度是指所有可能的輸入實例均以等概率出現的情況下,該算法的運行時間。

最壞情況下的時間複雜度稱最壞時間複雜度。一般討論的時間複雜度均是最壞情況下的時間複雜度。 這樣做的原因是:最壞情況下的時間複雜度是算法在任何輸入實例上運行時間的界限,這就保證了算法的運行時間不會比最壞情況更長。

P20-3.2排序算法之冒泡排序

package demo4;

import java.util.Arrays;

public class BubbleSort {

	public static void main(String[] args) {
		int[] arr = new int[] { 5, 7, 2, 9, 4, 1, 0, 5, 7 };
		System.out.println(Arrays.toString(arr));
		bubbleSort(arr);
		System.out.println(Arrays.toString(arr));
	}
	
	/**冒泡排序 
	 * 共需要比較length-1輪
	 * 5,7,2,9,4,1,0,5,7	【5、7】	
	 * 5,7,2,9,4,1,0,5,7	【7、2】
	 * 5,2,7,9,4,1,0,5,7	...
	 * 5,2,7,4,1,0,5,7,9
	 * 2,5   
	 */
	public static void bubbleSort(int[] arr) {
		// 控制共比較多少輪
		for (int i = 0; i < arr.length - 1; i++) {
			// 控制比較的次數
			for (int j = 0; j < arr.length - 1 - i; j++) { // 減i,比較過的數字,不再進行比較
				if (arr[j] > arr[j + 1]) {
					int temp = arr[j];
					arr[j] = arr[j + 1];
					arr[j + 1] = temp;
				}
			}
		}
	}
	
	// 冒泡排序優化
	public static void bubbleSort2(int[] arr) {
		// 控制共比較多少輪
		for (int i = 0; i < arr.length - 1; i++) {
			boolean flag = false;
			// 控制比較的次數
			for (int j = 0; j < arr.length - 1 - i; j++) { // 減i,比較過的數字,不再進行比較
				if (arr[j] > arr[j + 1]) {
					int temp = arr[j];
					arr[j] = arr[j + 1];
					arr[j + 1] = temp;
					flag = true; // 加入標記					
				}
			}
			if(flag) { // 如果沒有交換過元素,則已經有序!
				return;
			}
		}
	}
	
}

冒泡排序優化https://blog.csdn.net/hansionz/article/details/80822494 

P21-3.3排序算法之快速排序

設定一個基準數a。【通常取第一個數字!】

比a大的數字,往右移動;比a小的數字,往左移動!遞歸!!!

設置 前後 2個 標記,標記重合,進行下一次 遞歸!【遞歸結束條件:開始位置==結束位置】

package demo4;

import java.util.Arrays;

public class QuickSort {

	public static void main(String[] args) {
		int[] arr = new int[] { 3, 4, 6, 7, 2, 7, 2, 8, 0, 9, 1 };
		quickSort(arr, 0, arr.length - 1);
		System.out.println(Arrays.toString(arr));
	}

	public static void quickSort(int[] arr, int start, int end) {
		if (start < end) {
			// 把數組中的第0個數字做爲標準數
			int stard = arr[start];
			// 記錄需要排序的下標
			int low = start;
			int high = end;
			// 循環找比標準數大的數和比標準數小的數
			while (low < high) {
				// 右邊的數字比標準數大
				while (low < high && stard <= arr[high]) {
					high--;
				}
				// 使用右邊的數字替換左邊的數
				arr[low] = arr[high];
				// 如果左邊的數字比標準數小
				while (low < high && arr[low] <= stard) {
					low++;
				}
				arr[high] = arr[low];
			}
			// 把標準數賦給低所在的位置的元素
			arr[low] = stard;
			// 處理所有的小的數字
			quickSort(arr, start, low);
			// 處理所有的大的數字
			quickSort(arr, low + 1, end);
		}
	}

}

P22-3.4排序算法之插入排序

認爲所有的數字,都是有序的。將數字依次往前移動,一個一個插入到前面的有序序列中!

第2個數字開始取!

package demo4;

import java.util.Arrays;

public class InsertSort {

	public static void main(String[] args) {
		int[] arr = new int[] { 5, 3, 2, 8, 5, 9, 1, 0 };
		insertSort(arr);
		System.out.println(Arrays.toString(arr));
	}

	// 插入排序
	public static void insertSort(int[] arr) {
		// 遍歷所有的數字【從第2個數字開始比較!】
		for (int i = 1; i < arr.length; i++) {
			// 如果當前數字比前一個數字小
			if (arr[i] < arr[i - 1]) {
				// 把當前遍歷數字存起來
				int temp = arr[i];
				int j;
				// 遍歷當前數字前面所有的數字
				for (j = i - 1; j >= 0 && temp < arr[j]; j--) {
					// 把前一個數字賦給後一個數字
					arr[j + 1] = arr[j];
				}
				// 把臨時變量(外層for循環的當前元素)賦給不滿足條件的後一個元素
				arr[j + 1] = temp;
			}
		}
	}

}

P23-3.5排序算法之希爾排序

將 數組 分爲 4部分,每一部分都進行插入排序!

第1輪步長:4;【9/2 == 4】

第2輪步長:2;【4/2 == 2】

第3輪步長:1。【2/2 == 1】

package demo4;

import java.util.Arrays;

public class ShellSort {

	public static void main(String[] args) {
		int[] arr = new int[] { 3, 5, 2, 7, 8, 1, 2, 0, 4, 7, 4, 3, 8 };
		System.out.println(Arrays.toString(arr));
		shellSort(arr);
		System.out.println(Arrays.toString(arr));
	}

	public static void shellSort(int[] arr) {
		int k = 1;
		// 遍歷所有的步長
		for (int d = arr.length / 2; d > 0; d /= 2) {
			// 遍歷所有元素
			for (int i = d; i < arr.length; i++) {
				// 遍歷本組中所有的元素
				for (int j = i - d; j >= 0; j -= d) {
					// 如果當前元素大於加上步長後的那個元素
					if (arr[j] > arr[j + d]) {
						int temp = arr[j];
						arr[j] = arr[j + d];
						arr[j + d] = temp;
					}
				}
			}
			System.out.println("第" + k + "次排序結果:" + Arrays.toString(arr));
			k++;
		}
	}

}

P24-3.6排序算法之選擇排序

從第1個數字,開始往後找。

從第2個數字,開始往後找。

從第3個數字,開始往後找。

package demo4;

import java.util.Arrays;

public class SelectSort {

	public static void main(String[] args) {
		int[] arr = new int[] { 3, 4, 5, 7, 1, 2, 0, 3, 6, 8 };
		selectSort(arr);
		System.out.println(Arrays.toString(arr));
	}

	// 選擇排序
	public static void selectSort(int[] arr) {
		// 遍歷所有的數
		for (int i = 0; i < arr.length; i++) {
			int minIndex = i;
			// 把當前遍歷的數和後面所有的數依次進行比較,並記錄下最小的數的下標
			for (int j = i + 1; j < arr.length; j++) {
				// 如果後面比較的數比記錄的最小的數小。
				if (arr[minIndex] > arr[j]) {
					// 記錄下最小的那個數的下標
					minIndex = j;
				}
			}
			// 如果最小的數和當前遍歷數的下標不一致,說明下標爲minIndex的數比當前遍歷的數更小。
			if (i != minIndex) {
				int temp = arr[i];
				arr[i] = arr[minIndex];
				arr[minIndex] = temp;
			}
		}
	}

}

P25-3.7排序算法之歸併排序

package demo4;

import java.util.Arrays;

public class MergeSort {

	public static void main(String[] args) {
		int[] arr = new int[] { 1, 3, 5, 2, 4, 6, 8, 10 };//【3 1】
		System.out.println(Arrays.toString(arr));
		mergeSort(arr, 0, arr.length - 1);//【0 0 1】
		System.out.println(Arrays.toString(arr));
	}

	// 歸併排序
	public static void mergeSort(int[] arr, int low, int high) {
		int middle = (high + low) / 2;
		if (low < high) {
			// 處理左邊
			mergeSort(arr, low, middle);
			// 處理右邊
			mergeSort(arr, middle + 1, high);
			// 歸併
			merge(arr, low, middle, high);
		}
	}

	public static void merge(int[] arr, int low, int middle, int high) {
		// 用於存儲歸併後的臨時數組
		int[] temp = new int[high - low + 1];
		// 記錄第一個數組中需要遍歷的下標
		int i = low;
		// 記錄第二個數組中需要遍歷的下標
		int j = middle + 1;
		// 用於記錄在臨時數組中存放的下標
		int index = 0;
		// 遍歷兩個數組取出小的數字,放入臨時數組中
		while (i <= middle && j <= high) {
			// 第一個數組的數據更小
			if (arr[i] <= arr[j]) {
				// 把小的數據放入臨時數組中
				temp[index] = arr[i];
				// 讓下標向後移一位;
				i++;
			} else {
				temp[index] = arr[j];
				j++;
			}
			index++;
		}
		// 處理多餘的數據
		while (j <= high) {
			temp[index] = arr[j];
			j++;
			index++;
		}
		while (i <= middle) {
			temp[index] = arr[i];
			i++;
			index++;
		}
		// 把臨時數組中的數據重新存入原數組
		for (int k = 0; k < temp.length; k++) {
			arr[k + low] = temp[k];
		}
	}

}

P26-3.8排序算法之基數排序

大小都有,數字位數不一樣!

排序次數,取決於,數組中最大數字的位數!

 

先找出數組中最大的數字【int max = Integer.MIN_VALUE;】,

將數字轉爲字符串---計算位數【int maxLength = (max + "").length();】===》確定循環次數。

第1次,按照個位進行排序!

第2次,按照十位進行排序!

第3次,按照十位進行排序!

餘數:0~9   ==>   最多需要10個數組

package demo4;

import java.util.Arrays;

public class RadixSort {

	public static void main(String[] args) {
		int[] arr = new int[] { 23, 6, 189, 45, 9, 287, 56, 1, 798, 34, 65, 652, 5 };
		radixSort(arr);
		System.out.println(Arrays.toString(arr));
	}

	public static void radixSort(int[] arr) {
		// 存最數組中最大的數字
		int max = Integer.MIN_VALUE;
		for (int i = 0; i < arr.length; i++) {
			if (arr[i] > max) {
				max = arr[i];
			}
		}
		// 計算最大數字是幾位數
		int maxLength = (max + "").length();
		// 用於臨時存儲數據的二維數組
		int[][] temp = new int[10][arr.length];// arr.length 避免 空指針異常
		// 用於記錄在temp中相應的數組中存放的數字的數量
		int[] counts = new int[10];
		// 根據最大長度的數決定比較的次數
		for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {
			// 把每一個數字分別計算餘數
			for (int j = 0; j < arr.length; j++) {
				// 計算餘數
				int ys = arr[j] / n % 10;
				// 把當前遍歷的數據放入指定的數組中
				temp[ys][counts[ys]] = arr[j];
				// 記錄數量
				counts[ys]++;
			}
			// 記錄取的元素需要放的位置
			int index = 0;
			// 把數字取出來
			for (int k = 0; k < counts.length; k++) {
				// 記錄數量的數組中當前餘數記錄的數量不爲0
				if (counts[k] != 0) {
					// 循環取出元素
					for (int l = 0; l < counts[k]; l++) {
						// 取出元素
						arr[index] = temp[k][l];
						// 記錄下一個位置
						index++;
					}
					// 把數量置爲0
					counts[k] = 0;
				}
			}
		}
	}

}

P27-3.9基數排序之隊列實現

先放進去的先取;後放進去的後取。先進先出!!!隊列!!!

package demo4;

import java.util.Arrays;

import demo2.MyQueue;

public class RadixQueueSort {

	public static void main(String[] args) {
		int[] arr = new int[] { 23, 6, 189, 45, 9, 287, 56, 1, 798, 34, 65, 652, 5 };
		radixSort(arr);
		System.out.println(Arrays.toString(arr));
	}

	public static void radixSort(int[] arr) {
		// 存最數組中最大的數字
		int max = Integer.MIN_VALUE;
		for (int i = 0; i < arr.length; i++) {
			if (arr[i] > max) {
				max = arr[i];
			}
		}
		// 計算最大數字是幾位數
		int maxLength = (max + "").length();
		// 用於臨時存儲數據的隊列的數組
		MyQueue[] temp = new MyQueue[10];
		// 爲隊列數組賦值
		for (int i = 0; i < temp.length; i++) {
			temp[i] = new MyQueue();
		}
		// 根據最大長度的數決定比較的次數
		for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {
			// 把每一個數字分別計算餘數
			for (int j = 0; j < arr.length; j++) {
				// 計算餘數
				int ys = arr[j] / n % 10;
				// 把當前遍歷的數據放入指定的隊列中
				temp[ys].add(arr[j]);
			}
			// 記錄取的元素需要放的位置
			int index = 0;
			// 把所有隊列中的數字取出來
			for (int k = 0; k < temp.length; k++) {
				// 循環取出元素
				while (!temp[k].isEmpty()) {
					// 取出元素
					arr[index] = temp[k].poll();
					// 記錄下一個位置
					index++;
				}
			}
		}
	}

}

多謝觀看~~~

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