创建一个数组来表示待排序和搜索的数据结构
function ArrayList(){
var array= [];
this.insert= function(item){ //插入方法来添加元素
array.push(item);
};
this.toString= function(){ //将数组元素拼接成一个字符串,并返回该字符串
return array.join();
};
}
1-冒泡排序 复杂度O(n^2)
this.bubbleSort= function(){
var length= array.length;
for (var i=0; i<length; i++){
for (var j=0; j<length-1-i; j++){
if (array[j] > array[j+1]){
swap (array, j, j+1);
}
}
}
};
声明swap函数(私有函数,只能在ArrayList类内部使用)
var swap= function(array, index1, index2) {
var aux= array[index1];
array[index1]= array[index2];
array[index2]= aux;
};
2-选择排序 复杂度O(n^2)
是一种原址比较排序算法,大致思路是找最小的并将其放在第一位,再接着找第二小的放在第二位,以此类推。
this.selectionSort= function(){
var length= array.length;
var indexMin;
for (var i=0; i<length-1; i++){
indexMin= i;
for (var j=0; j<length; j++){
if (array[indexMin] > array[j]){
indexMin= j;
}
}
if (i !== indexMin){
swap(i, indexMin);
}
}
};
3-插入排序 每次排一个数组项,排序小型数组时性能优于冒泡排序和选择排序
this.insertionSort= function(){
var length= array.lenth;
var j, temp;
for (var i=0; i<lenth; i++){
j= i;
temp= array[i];
while (j>0 && array[j-1]>temp){
array[j]= array[j-1];
j–;
}
array[j]= temp;
}
};
4-归并排序 复杂度O(n log^n)
是一种分治算法,思想是将原始数组切分成较小的数组,直到每个小数组只有一个位置,接着将小数组归并成较大数组,直至最后只有一个排序完毕的大数组。
归并排序也是递归的
this.mergeSort= function(){
array= mergeSortRec(array);
};
声明递归函数mergeSortRec()
var mergeSortRec= function(array){
var length= array.length;
if (length == 1){
return array;
}
var mid= Math.floor(length/2),
left= array.slice(0, mid),
right= array.slice(mid, length);
return merge( mergeSortRec(left), mergeSortRec(right) );
};
声明merge()函数:接受两个数组作为参数,将它们归并至一个大数组
var merge= function(left, right){
var result= [],
il= 0,
lr= 0;
while( il<left.length && ir<right.length){
if( left[il] < right[ir] ){
result.push( left[il++] );
} else {
result.push( right[ir++] );
}
}
while( il<left.length){
result.push( left[il++] );
}
while( ir<right.length){
result.push( right[ir++] );
}
return result;
};
5-快速排序 复杂度O(n log^n),且性能通常比其他O(n log^n)的排序算法要好
快速排序也使用分治的方法,将原始数组分成较小的数组:
a-从数组中选择中间一项作为主元;
b-划分操作:创建两个指针,左边一个指向数组的第一项,右边指向数组最后一项。移动左指针直到找到一个比主元大的元素,再移动右指针直到找到一个比主元小的元素,然后交换它们,重复这个过程,直至左指针超过了右指针。
c-对划分后的小数组(比主元小的元素组成的子数组、比主元大的元素组成的子数组)重复之前的操作,直至数组已完全排序。
声明一个主方法来调用递归函数
this.quickSort= function(){
quick( array, 0, array.length-1); //待排序数组,索引0,最末位置
};
var quick= function( array, left, right){
var index; //将数组分离成较小值数组和较大值数组
if ( array.lenth>1 ){
index= partition( array, left, right); //{3}
if( left< index-1){
quick( array ,left ,index-1);
}
if ( index< right){
quick( array, index, right);
}
}
};
划分过程
var partition= function(array, left, right){
var pivot= array[ Math.floor( (right+left)/2 )], //选择中间项作为主元 接下来初始化两个指针
i= left, //left初始化为数组的第一个元素
j= right; //right初始化为数组的最后一个元素
while( i<=j ){ //只要left和right没有交错,就划分
while( array[i]<pivot ){
i++;
}
while( array[j]>pivot ){
j–;
}
if ( i<=j ){
swap(array, i, j);
i++;
j–;
}
}
return i; //划分结束,返回左索引,用来在{3}处创建子数组
};
6-堆排序 把数组当二叉树来管理
索引0是树的根节点;
除根节点外,任何节点的父节点是N/2;
节点L的左子节点是2*L;
节点R的右子节点是2*R+1。
this.heapSort= function(){
var heapSize= array.length;
bulidHeap( array); //构建一个array[parent(i)]>=array[i]的堆结构
while( heapSize>1){
heapSize–;
swap( array, 0, heapSize); //交换堆里的第一个和最后一个元素的位置,
heapify( array, heapSize, 0); //再次将数组转换成堆
}
};
var buildHeap= function(){
var heapSize= array.length;
for( var i= Math.floor(array.length/2); i>=0; i–){
heapify( array, heapSize, i);
}
};
heapify()函数:找到当前堆的根节点(较小的值),重新放到树的底部
var heapify= function( array ,heapSize ,i ){
var left= i*2+1,
right= i*2+2,
largest= i;
if( left<heapSize && array[left]>array[largest]){
largest= left;
}
if( right<heapSize && array[right]>array[largest]){
largest= right;
}
if(largest !== i){
swap( array , i, largest);
heapify( array, heapSize, largest);
}
};
时间复杂度:
算法(数组) | 时间复杂度 | ||
最好情况 | 一般情况 | 最坏情况 | |
冒泡排序 | O(n) | O(n^2) | |
选择排序 | O(n^2) | ||
插入排序 | O(n) | O(n^2) | |
归并排序 | O( nlog(n) ) | ||
快速排序 | O( nlog(n) ) | O(n^2) | |
堆排序 | O( nlog(n) ) | ||
桶排序 | O( n+k ) | O(n^2) | |
基数排序 | O( nk ) |