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://github.com/zhangdanzhu/basic_data-structure_algorithm/blob/master/sort/cpp/selection_sort.cpp