冒泡排序
冒泡排序比较任何两个相邻的项,如果第一个比第二个大,则交换它们。元素项向上移动到正确的顺序,就好像气泡升至表面一样,冒泡排序因此得名。
基本的冒泡排序
function bubbleSort(arr){
let length = arr.length;
// 交换函数
function swap(arr, index1, index2){
let item = arr[index1];
arr[index1] = arr[index2];
arr[index2] = item;
//ES6中可写为 [arr[index1],arr[index2]] = [arr[index2],arr[index1]]
}
for(let i = 0; i < length; i++){
for(let j = 0; j < length-1; j++){
if(arr[j] > arr[j+1]){
swap(arr, j, j+1);
}
}
}
return arr;
}
第一次外循环确定了最后一个值,第二次外循环确定了倒数第二个值,第三次外循环确定了倒数第三个值.....依此类推。
改进后的冒泡排序
function bubbleSort(arr){
let length = arr.length;
// 交换函数
function swap(arr, index1, index2){
let item = arr[index1];
arr[index1] = arr[index2];
arr[index2] = item;
}
for(let i = 0; i < length; i++){
//内循环中减去外循环中已跑过的轮数,避免不必要的比较
for(let j = 0; j < length-1-i; j++){
if(arr[j] > arr[j+1]){
swap(arr, j, j+1);
}
}
}
return arr;
}
每次外循环都确定一个值的位置,所以没必要在内循环中每次都循环(length-1)次,而是改为(length-1-i)
选择排序
选择排序是找到数组中的最小值放到第一位,接着找到第二小的值并将其放到第二位,依此类推。
function selectSort(arr){
let length = arr.length;
let minIndex; //最小值的下标
// 交换函数
function swap(arr, index1, index2){
[arr[index1],arr[index2]] = [arr[index2],arr[index1]]
}
for(let i = 0; i < length-1; i++){
minIndex = i;//第一次循环放第一个位置,第二次循环放第二个位置...
for(let j = i; j < length; j++){
if(arr[minIndex] > arr[j]){
minIndex = j; //找到最小值的下标
}
}
if(i !== minIndex){ //如果找到的最小值下标不等于i
swap(arr, i, minIndex) //交换位置
}
}
return arr;
}
插入排序
假设第一项已经排序了,接着让第二项和他比较,决定第二项排在第一项之前还是之后,这样头两项就排好了,然后用第三项和前两项比较,确定前三项的顺序,依此类推。
function insertionSort(arr){
let length = arr.length;
let j = 0;
let temp = 0;
for(let i = 1; i < length; i++){
j = i; //避免死循环,所以用j代理i做内循环
temp = arr[i];
while(j > 0 && arr[j-1] > temp){
arr[j] = arr[j-1];
j--;
}
arr[j] = temp;
}
return arr;
}
此算法比选择排序和冒泡排序性能要好,但是没有下面几个性能好
归并排序
归并排序是一种分治算法,思路是将原始数组切分成较小的数组,直到每个小数组只有一个元素,接着将小数组排序归并成较大的数组,直到最后只有一个排序完毕的大数组。
let merge = function(left,right){
let result = [];
let il = 0;
let ir = 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;
}
let mergeSortRec = function(arr){
let length = arr.length;
//一直分到数组长度为1,直接返回该数组
if(length === 1){
return arr;
}
let mid = Math.floor(length/2);
let left = arr.slice(0,mid);
let right = arr.slice(mid,length);
return merge(mergeSortRec(left),mergeSortRec(right));//递归
}
其中mergeSortRec函数把数组转化为多个小数组直到只有一个项,merge函数合并排序小数组最后回到原始数组。merge函数可以把任意两个有序数组进行合并为一个有序数组。例如:
merge([1,7,11],[2,3,5,8,13]) //[1,2,3,5,7,8,11,13]