冒泡排序
描述
依次比较相邻的数据,将小数据放在前,大数据放在后。即第一趟先比较第1个和第2个数,大数在后,小数在前,再比较第2个数与第3个数,大数在后,小数在前,直到将最大的数移动到最后一个位置。第二趟则将次大的数移动到倒数第二个位置,...直到将第n大的数移动到第一个输的位置,便完成排序。
实现
冒泡排序的核心操作是对两个数据进行比较和进行交换。具体做法如下(假设需要排序的数据存在一个数组变量array里面,从左往右,从小到大排序):
设置变量 i=0,j=i+1 ;
取 a=array[i] ;
从数组第j个元素开始,取 b=array[j] ;
比较 a>b ?,如果 a>b 为真,交换 a 和 b 对应数组的值,否则不做交换。继续循环, j+1 ;
当 j>=array.length 时,结束循环,否则继续 3-5 步。
i=i+1 ;
重复操作 2-6 直到i>=array.length,算法结束,得到的array的值就是排序完成的数组。
/**
* 冒泡,升序
* @param {array} array 数值数组
* @return {array} 排好序的数据,不该变原数组
*/
function bubbleSort (array) {
let tempArray = [].concat(array)
let i = 0;
let j = 0;
let len = tempArray.length
for (i = 0; i < len; i++) {
for (j = i + 1; j < len; j++) {
let a = tempArray[i];
let b = tempArray[j];
if (a > b) {
tempArray[i] = b;
tempArray[j] = a;
}
}
}
return tempArray;
}
bubbleSort([9,8,7,6,5,4,3,2,1]);
视频演示:http://v.youku.com/v_show/id_XMzMyOTAyMzQ0.html
总结
冒泡排序的核心操作是比较和数据交换.时间复杂为O(n^2),是稳定的排序算法,但是效率并不高。
选择排序
选择排序可以看作是冒泡排序的一种优化。在冒泡排序的过程中,会做许多无用的数据交换,因为在冒泡排序里,交换数据只能保证当前两个数据的正确排序位置,但很可能不是最后的排序位置。也就是说,之后这个两个数据可能还需要和其其它数据交换位置,才能得到最后的结果。这样就会产生许多无用的数据交换操作,这也是冒泡排序效率不高的一个原因。选择排序集针对这一点做了优化,他依然想冒泡排序那样比较数据,不同之处在于,在满足数据交换的条件时,并不立即进行数据交换的操作,而是记录该数据的位置,当该数据与所有的数据比较完成后,最后在进行数据交换的操作。
描述
选择排序从数组的开头开始,将第一个元素和其他元素进行比较。检查完所有元素后,最小的元素会被放到数组的第一个位置,然后算法会从第二个位置继续。这个过程一直进行,当进行到数组的倒数第二个位置时,所有的数据便完成了排序。
实现
具体实现过程如下((假设需要排序的数据存在一个数组变量array里面,左往右,从小到大排序):
设置变量 i=0 ;
取 temp=i,j=i;
从数组元素第j个元素开始循环。
比较 array[temp]>array[j] ? ,若 array[temp]>array[j] 为真,那么 temp=j,j=j+1 ;
如果 j>=array.length ,则结束循环,否则继续执行 4-5 ;
交换数组元素 array[i] 和 array[temp] 的值, i=i+1 ;
如果 i>=array.length ,则结束循环,得到的数据就是完成排序的数组,否则继续执行 2-6 步;
function chooseSort(array) {
var temp = -1;
for (var i = 0; i < array.length; i++) {
//寻找i以及i元素之后,最小的数组元素
temp = i;
for (var j = i; j < array.length; j++) {
if (array[temp] > array[j]) {
temp = j;
}
}
//每次内存循环最多交换一次
if (temp != j) {
var tempData = array[i];
array[i] = array[temp];
array[temp] = tempData;
}
}
return array;
}
视频演示:http://v.youku.com/v_show/id_XMzMyODk5MDI0.html
总结
选择排序的效率会比冒泡的效率高(在排序的数据量非常大的情况下),因为他减少了许多无用的数据交换操作,而数据交换操作相对于数据比较操作是很耗时的。选择排序的时间复杂度为O(n^2),算法是稳定的。
插入排序
描述
插入排序有两个循环。外循环将数组元素挨个移动,而内循环则对外循环中选中的元素及它后面的那个元素进行比较。如果外循环中选中的元素比内循环中选中的元素小,那么数组元素会向右移动,为内循环中的这个元素腾出位置。
实现
从第一个元素开始,该元素可以认为已经被排序
取出下一个元素,在已经排序的元素序列中从后向前扫描
如果该元素(已排序)大于新元素,将该元素移到该元素的下一位置
重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
将新元素插入到该位置后
重复步骤2~5
function insertOrder(array) {
var len = array.length;
for (var i = 1; i < len; i++) {
var temp = array[i],
j = i;
while (j > 0 && array[j - 1] > temp) {
array[j] = array[j - 1];
j--;
}
array[j] = temp;
}
return array;
}
视频演示:http://v.youku.com/v_show/id_XMjU4NTY5MzEy.html
结论
插入排序的时间复杂度为O(n^2),算法是稳定的。