O(n^2)的排序算法
- O(n^2)是比较基础的排序算法,效率较低,编码简答,易于实现,是一些简单情景的首选。
- 在一些特殊的情况下,简单的排序算法更有效
- 简单的排序算法思想衍生出复杂的排序算法
- 作为子过程,改进更复杂的排序算法
选择排序 Selection Sort
需要将下列数从小到大排列
从第一个开始排,找到比第一个(8)后面最小的数,是1
然后将其交换位置
此时的1就是最终排序的位置
后面的依次类推
C++代码实现
#include <iostream>
#include <algorithm>
using namespace std;
void selectionSort(int arr[], int n){
for(int i = 0 ; i < n ; i ++){
// 寻找[i, n)区间里的最小值
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,2,5,7,9,3,4,8,6,1};
selectionSort(a,10);
for( int i = 0 ; i < 10 ; i ++ )
cout<<a[i]<<" ";
cout<<endl;
return 0;
}
稍加改造一下函数,使其对各种类型都通用
#include <iostream>
#include <string>
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};
selectionSort( a , 10 );
for( int i = 0 ; i < 10 ; i ++ )
cout<<a[i]<<" ";
cout<<endl;
// 测试模板函数,传入浮点数数组
float b[4] = {4.4,3.3,2.2,1.1};
selectionSort(b,4);
for( int i = 0 ; i < 4 ; i ++ )
cout<<b[i]<<" ";
cout<<endl;
// 测试模板函数,传入字符串数组
string c[4] = {"D","C","B","A"};
selectionSort(c,4);
for( int i = 0 ; i < 4 ; i ++ )
cout<<c[i]<<" ";
cout<<endl;
return 0;
}
结果:1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1.1 2.2 3.3 4.4
A B C D
插入排序 Insert Sort
虽然作为O(n^2)的排序算法,但在数组近乎有序的情况下,它的排序效率及其的高,甚至比O(nlogn)的算法效率还要高,可以作为复杂算法中的子过程。
需要将下列数从小到大排列
先将第二个数(6)与前面的数相比较,小的话就交换位置
然后再看第三个数(2)跟前面的数相比较,2<8,所以交换位置,再继续跟前面的数(6)比较,2<6,所以继续交换位置
后面的依次类推
C++代码实现
template<typename T>
void insertionSort(T arr[], int n){
for( int i = 1 ; i < n ; i ++ ) {
// 寻找元素arr[i]合适的插入位置
// 写法1
// for( int j = i ; j > 0 ; j-- )
// if( arr[j] < arr[j-1] )
// swap( arr[j] , arr[j-1] );
// else
// break;
// 写法2
for( int j = i ; j > 0 && arr[j] < arr[j-1] ; j -- )
swap( arr[j] , arr[j-1] );
}
return;
}
改进版的插入排序
由于前面的插入排序一个swap需要经过三步,效率不是很高,以下是改进版的插入排序算法,不使用swap进行交换,而是通过先将数复制下来,再与前面的进行比对,总体思想是一样的。
先把第二个数(6)复制一份,先看看它适不适合放在当前位置,让6跟前面的数(8)作比较,因为6<8,所以显然不适合当前位置,而8适合当前位置。
把6往后移,因为是第一个元素了,所以直接把6放在这个位置
后面依次类推
C++代码实现
void insertionSort(T arr[], int n){
for( int i = 1 ; i < n ; i ++ ) {
// 写法3
T e = arr[i];
int j; // j保存元素e应该插入的位置
for (j = i; j > 0 && arr[j-1] > e; j--)
arr[j] = arr[j-1];
arr[j] = e;
}