排序算法O(n*2)
这种比较基础,很多时候我们在面临一个问题要从最简单的方法解决,从而优化
编码简单,易于实现,是一些简单场景的首选,汇编语言也可以用
特殊情况下,简单排序更加有效
能延伸更复杂的排序,如希尔排序
作为子过程,用于改进更加负载的排序算法
选择排序
8,6,2,3,1,5,7,4
首先在整个数组找到第一名 1,将1和8交换,1就是最终位置,之后找最小的以此类推
具体实现如下
template<typename T>
void selectionSort( T arr[] , int n){
for(inti=0 ; i<n ; i++){
//寻找[i,n)最小值
intminIndex = i;
for(int j = i+1 ; j < n ; j++)
if(arr[j] < arr[minIndex])
minIndex= j;
swap(arr[i] , arr[minIndex]);
}
}
以下是php版本
<?php function selectionSort(array $arr){ $n = count($arr); for($i=0;$i<$n;$i++){ $minIndex = $i; for($j = $i+1 ; $j < $n ; $j++){ if($arr[$j] < $arr[$minIndex]) $minIndex=$j; } $temp = $arr[$i]; $arr[$i] = $arr[$minIndex]; $arr[$minIndex] = $temp; } return $arr; } $a = [5,6,1,23,56,7]; $a = selectionSort($a); var_dump($a);
插入排序:Insertion Sort整理扑克牌
把每张牌插入合适位置,当最后一张操作完成就结束了
首先对第一个元素不动,看第二个,把第二个放入前面合适的位置
template<typename T>
void insertionSort(T arr[], int n ){
for(int i = 1 ; i<n ;i++){
//第0个元素已经有序了
//寻找元素arr[i]合适的插入位置
for(intj = i; j>0&&arr[j] < arr[j-1];j--){
swap(arr[j],arr[j-1]);
}
}
}
插入排序和选择排序的区别:插入排序第二次循环可以提前结束,理论上所以插入更快一些,但是实际却不是这样。
插入排序的在遍历的通时也在不停地交换,遍历比比较操作耗时,因为每一次交换,都要3次赋值。对数组还要访问索引所在元素。
先把i复制一个副本,看看i是不是该待在i,i比i-1如果小,i不该在这个位置,所以把i-1放到i….
改进后的插入排序
template<typename T>
void insertionSort(T arr[], int n ){
for(int i = 1 ; i<n ;i++){
//第0个元素已经有序了
//寻找元素arr[i]合适的插入位置
Te = arr[i];
intj;//j保存元素e应该插入的位置
for(intj = i; j>0&&arr[j-1] > e;j--){
arr[j] = arr[j-1];
}
arr[j] = e;
}
}
不但不用交换,还提前终止所以就比较快了。加入本身基本上就有序,可以很快找到位置,此时插入排序效率比较高,有序性高的话就比较快。我们很多时候都是有这种近乎有序的。
如果完全有序就是o(n)。插入排序在很多排序中作为子排序优化。
以下是php版本
<?php function insertionSort(array $arr){ $n = count($arr); for($i =1;$i<$n;$i++){ $e = $arr[$i]; for($j=$i;$j>0&&$arr[$j-1]>$e;$j--){ $arr[$j] = $arr[$j-1]; } $arr[$j] = $e; } return $arr; } $a = [5,6,1,23,56,7]; $a = insertionSort($a); var_dump($a);
辅助:
生成1000个数
在文件SortTestHelper.h中声明一系列辅助函数
把他们放在一个命名空间中
#include <iosstream>
#include <ctime>
#inclde <cassert>
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;
returnarr;
}
生成近乎随机
int *generateNearlyOrderedArray(intn , int swaptimes){
int *arr = new int[n];
for(int i=0;i<n;i++)
arr[i]=i;
sand(time(Null));
for(int i=0 ;i< swapTimes;i++){
int posx =rand()%n;
int posy =rand()%n;
swap(arr[posx], arr[posy]);
}
}
template<typenameT>
voidprintArray(T arr[],int n){
for (int i=0;i<n;i++)
cout<<arr[i]<< ” ”;
cout << endl;
return;
}
//测试排序算法
template<typenameT>
void testSort(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) );//不放在endTime前因为性能不能包含,会干扰,而且如果sort错误那么打印输出会中断
cout << sortName <<” : ” <<double(endTime -startTime) / CLOCKS_PER_SEC<<” s”<<endl;
return;
// CLOCKS_PER_SEC标准库定义的宏,每秒钟运行的时钟周期个数
}
int*copyIntArray(int a[],int n){
int* arr = new int[n]
copy(a,a+n,arr);
return arr;
}
template<typenameT>
bool isSorted(Tarr[], int n){
for(int i=0;i<n-1;i++)
if(arr[i]>arr[i+1])
return false;
return true;
}
}
测试用例:
#inclue “SortTestHelper.h”
int main(){
intn =10000;
int*arr = SortTestHelper:: generateRandomArray selectionSort(n,0,n);
// selectionSort(arr , n );
// SortTestHelper::printArray(arr,n);
SortTestHelper::testSort(“SelectionSort”, selectionSort, arr,n);
delete[]arr; //内存释放,防止内存泄露
return0;
}