自行总结:从越来越小的选择区间中选择一个最小(大)的值,和选择区间最前面的值交换位置
,直到排序完成
main.cpp
#include
using namespace std;
void selectionSort(int arr[], int n){
// 一层循环,缩小寻找最小值的区间范围
for(int i = 0; i < n; i ++){
// 二层循环,寻找[i, n)区间里的最小值的index
int minIndex = i;
for( int j = i + 1; j < n; j ++ ){
if( arr[j] < arr[minIndex])
minIndex = j;
}
// 二层循环完毕,区间最小值和区间第一交换位置,放到区间最前面
// swap函数,进行交换
swap(arr[i], arr[minIndex]);
}
}
int main() {
int a[10] = {10,9,8,7,6,5,4,3,2,1};
selectionSort(a, 10);
for ( int i = 0; i < 10; i ++ )
cout<<a[i]<<" ";
cout<<endl;
return 0;
}
注:对于c++实现,整数,浮点和字符串数组可通过写泛型参数实现,而集合数组
则需要写类实现(以后再研究代码吧)
function selectionSort(arr, n){
// 一层循环,缩小寻找最小值的区间范围
for(let i = 0; i < n; i++){
// 二层循环,寻找[i, n)区间里的最小值的index
let minIndex = i;
for(let j = i+1; j < n; j++){
if(arr[j]<arr[minIndex]){
minIndex = j;
}
}
// 二层循环完毕,区间最小值和区间第一交换位置,放到区间最前面
// es6解构赋值,进行交换
[arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];
}
return arr;
}
selectionSort([10,9,8,7,6,5,4,3,2,1],10);
selectionSort([10,9,8,7,6,5,4,3,2,1],10);
(10) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
selectionSort([5.5,4.5,3.5,2.5,1.1],5);
(5) [1.1, 2.5, 3.5, 4.5, 5.5]
selectionSort([‘d’,‘a’,‘f’,‘c’,‘b’],5);
(5) [“a”, “b”, “c”, “d”, “f”]
注:对于js实现,整数,浮点和字符串数组都可通用,而集合数组
则取具体属性比较便可用
浮点和字符串数组可通过写泛型参数实现
#include
#include
using namespace std;
// 定义泛型
template<typename T>
void selectionSort(T arr[], int n){
for(int i = 0 ; i < n ; i ++){
int minIndex = i;
for( int j = i + 1 ; j < n ; j ++ )
if( arr[j] < arr[minIndex] )
minIndex = j;
swap( arr[i] , arr[minIndex] );
}
}
int main() {
// 整型数组
// int a[10] = {10,9,8,7,6,5,4,3,2,1};
// 浮点型数组
// float a[10] = {10.1,9.9,8.8,7.8,6.6,5.5,4.4,3.3,2.2,1.1};
// 字符串数组
string a[10] = {"a","c","f","e","g","h","i","b","l","p"};
selectionSort(a, 10);
for ( int i = 0; i < 10; i ++ )
cout<<a[i]<<" ";
cout<<endl;
return 0;
}
添加集合的类,对操作符(小于号)进行重载(也就是重新定义),去设置比较集合中的属性值
Student.h
#ifndef UNTITLED_STUDENT_H
#define UNTITLED_STUDENT_H
#include
#include
using namespace std;
struct Student{
string name;
int score;
// 小于号运算符的重载
bool operator<(const Student &otherStudent){
return score < otherStudent.score;
}
friend ostream& operator<<(ostream &os, const Student &student){
os<<"Student: "<<student.name<<" "<<student.score<<endl;
return os;
}
};
#endif //UNTITLED_STUDENT_H
main.cpp
#include
#include
#include "Student.h"
using namespace std;
// 定义泛型
template<typename T>
void selectionSort(T arr[], int n){
for(int i = 0 ; i < n ; i ++){
int minIndex = i;
for( int j = i + 1 ; j < n ; j ++ )
if( arr[j] < arr[minIndex] )
minIndex = j;
swap( arr[i] , arr[minIndex] );
}
}
int main() {
Student a[4] = {{"D", 98}, {"C", 100}, {"B", 95}, {"A", 95}};
selectionSort(a, 4);
for ( int i = 0; i < 4; i ++ )
cout<<a[i]<<" ";
cout<<endl;
return 0;
}
如果分数相同的情况下,再比较名字的大小,则对小于号的重载变为三目运算符
Student.h
#ifndef UNTITLED_STUDENT_H
#define UNTITLED_STUDENT_H
#include
#include
using namespace std;
struct Student{
string name;
int score;
// 小于号运算符的重载
// 分数不等,小于号比的是分数
// 分数相等,小于号比名字
// 注意:这里的排序顺序(升序或降序)完全可以自定义了
bool operator<(const Student &otherStudent){
return score != otherStudent.score ?
score < otherStudent.score : name < otherStudent.name;
// return score < otherStudent.score;
}
friend ostream& operator<<(ostream &os, const Student &student){
os<<"Student: "<<student.name<<" "<<student.score<<endl;
return os;
}
};
#endif //UNTITLED_STUDENT_H
创建统计时间所必要的工具参数
SortTestHelper.h
#ifndef INC_03_SELECTION_SORT_DETECT_PERFORMANCE_SORTTESTHELPER_H
#define INC_03_SELECTION_SORT_DETECT_PERFORMANCE_SORTTESTHELPER_H
#include
#include
#include
#include
using namespace std;
namespace SortTestHelper {
// 生成有n个元素的随机数组,每个元素的随机范围为[rangeL, rangeR]
int *generateRandomArray(int n, int rangeL, int rangeR) {
assert(rangeL <= rangeR);
int *arr = new int[n];
srand(time(NULL));
for (int i = 0; i < n; i++)
arr[i] = rand() % (rangeR - rangeL + 1) + rangeL;
return arr;
}
// 打印数组
template<typename T>
void printArray(T arr[], int n) {
for (int i = 0; i < n; i++)
cout << arr[i] << " ";
cout << endl;
return;
}
// 判断是否打印成功
template<typename T>
bool isSorted(T arr[], int n) {
for (int i = 0; i < n - 1; i++)
if (arr[i] > arr[i + 1])
return false;
return true;
}
// 计算排序时间
template<typename T>
void testSort(const string &sortName, void (*sort)(T[], int), T arr[], int n) {
clock_t startTime = clock();
sort(arr, n);
clock_t endTime = clock();
assert(isSorted(arr, n));
cout << sortName << " : " << double(endTime - startTime) / CLOCKS_PER_SEC << " s" << endl;
return;
}
};
#endif //INC_03_SELECTION_SORT_DETECT_PERFORMANCE_SORTTESTHELPER_H
main.cpp
#include
#include "SortTestHelper.h"
using namespace std;
template<typename T>
void selectionSort(T arr[], int n){
for(int i = 0 ; i < n ; i ++){
int minIndex = i;
for( int j = i + 1 ; j < n ; j ++ )
if( arr[j] < arr[minIndex] )
minIndex = j;
swap( arr[i] , arr[minIndex] );
}
}
int main() {
// 从测试可以看出数据变大十倍,执行时间变大百倍,时间复杂度度n方
// Selection Sort : 0.130219 s
// int n = 10000;
// Selection Sort : 11.44 s
int n = 100000;
int *arr = SortTestHelper::generateRandomArray(n,0,n);
SortTestHelper::testSort("Selection Sort", selectionSort, arr, n);
delete[] arr;
return 0;
}
注意:数组数量级增加10倍,排序时间增加100倍,时间复杂度n方
如果分数相同的情况下,再比较名字的大小,则比较判断的地方也变为三目运算符
function selectionSort(arr, n){
for(let i = 0; i < n; i++){
let minIndex = i;
for(let j = i+1; j < n; j++){
if(arr[j].age != arr[minIndex].age ?
arr[j].age < arr[minIndex].age :
arr[j].name < arr[minIndex].name){
minIndex = j;
}
}
[arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];
}
return arr;
}
selectionSort([{name:'b',age:2},{name:'a',age:1},{name:'e',age:3},{name:'c',age:3}],4);
// 生成随机数组
function getRandom(n){
let arr = [];
for (let i = 0; i < n; i++){
arr[i] = Math.floor(Math.random() * n);
}
return arr;
}
// 选择排序
function selectionSort(arr, n){
// 一层循环,缩小寻找最小值的区间范围
for(let i = 0; i < n; i++){
// 二层循环,寻找[i, n)区间里的最小值的index
let minIndex = i;
for(let j = i+1; j < n; j++){
if(arr[j]<arr[minIndex]){
minIndex = j;
}
}
// 二层循环完毕,区间最小值和区间第一交换位置,放到区间最前面
// es6解构赋值,进行交换
[arr[i], arr[minIndex]] = [arr[minIndex], arr[i]];
}
return arr;
}
// 统计排序执行时间
console.time("sort");
selectionSort(getRandom(10000),10000);
console.timeEnd("sort");