【從頭學數據結構和算法】選擇排序及其優化(c++實現)

c++實現的選擇排序及其優化



普通選擇排序

原理

每次從爲排序區間選擇一個最小的數據與前面的交換。

性質

  • 時間複雜度
    ——最好、最壞和平均:O(n^2)
  • 空間複雜度
    ——O(1):原地排序
  • 穩定性
    ——不穩定!!!

代碼

template<typename T> 
void select_sort0(T *a, int len) {
	// 首先檢查數據的合法性(TODO 不完善).
	if (a == NULL || len <= 1) {
		return;
	}
	
	int min = 0;	// 當前待排序的數據中最小值的下標 
	int j = 0;		// 內層循環(移動數據)計數變量   
	T temp = 0;		// 用於數據交換的臨時變量 
	
	// 對未排序區間進行遍歷 
	for (int i = 0; i < len; ++i) {
		min = i;
		// 在未排序區間中查找最小值 
		for (j = i+1; j < len; ++j) {
			if (a[j] < a[min]) {
				// 更新最小值下標 
				min = j; 
			}
		}  
		// 數據交換 
		temp = a[i];
		a[i] = a[min];
		a[min] = temp; 
	} 
} 

優化1:一次找最大最小兩值

原理

與普通的相同,只不過每次找最小和最大兩值,然後交換兩端的數據

性質

  • 時間複雜度
    ——最好、最壞和平均:O(n^2)【耗時是普通方法的一半左右】
  • 空間複雜度
    ——O(1):原地排序
  • 穩定性
    ——不穩定!!!

代碼

template<typename T> 
void select_sort1(T *a, int len) {
	// 首先檢查數據的合法性(TODO 不完善).
	if (a == NULL || len <= 1) {
		return;
	}
	
	int min = 0;	// 當前待排序的數據中最小值的下標 
	int max = 0; 	// 當前待排序的數據中最小值的下標 
	int j = 0;		// 內層循環(移動數據)計數變量
	int k = len;   	// 記錄已排序空間中最大值的交換位 
	T temp = 0;		// 用於數據交換的臨時變量 
	
	// 對未排序區間進行遍歷 (每次更新頭尾的位置)
	for (int i = 0; i < k; ++i,--k) {
		min = i;
		max = i; 
		// 在未排序區間中查找最小值和最小值 
		for (j = i+1; j < k; ++j) {
			if (a[j] < a[min]) {
				// 更新最小值下標
				min = j; 
			}
			if (a[j] > a[max]) {
				// 更新最大值下標 
				max = j;
			} 
		} 
		if (min != i) {
			// 數據交換-最小值 
			temp = a[i];
			a[i] = a[min];
			a[min] = temp; 
		} 
		if (max == i) {
			// 防止之前的已經被換掉
			max = min; 
		}
		if (max != k-1) {
			// 數據交換-最大值 
			temp = a[k-1];  
			a[k-1] = a[max];
			a[max] = temp;	
		} 
	} 
} 

測試

以20000個整數進行測試,記錄時間,同時assert是否與algorithm中sort結果相同。測試代碼略,可見完整代碼中。
測試結果時間(同時,assert未報錯)如下圖所示:
![在這裏插入圖片描述]
可見,優化效率提升基本接近於2倍,而且選擇排序本身也比冒泡排序要快(詳情見【從頭學數據結構和算法】冒泡排序及其優化(c++實現)(https://blog.csdn.net/ZhangDanzhu/article/details/96277870))。


完整代碼

排序及優化及測試 完整代碼在:
https://github.com/zhangdanzhu/basic_data-structure_algorithm/blob/master/sort/cpp/selection_sort.cpp

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