思路:比较和交换。每次把当前未排序的数据中最大的数据找出,放在最后。往水里扔个大石头,石头下沉,比石头轻的气泡上升。算法
function bubbleSort(array) {
var length = array.length;
for (let j = length; j > 1; j--) {
let exchange = false;
for (let i = 0; i < j-1; i++) {
if (array[i] > array[i+1]) {
let temp = array[i];
array[i] = array[i+1];
array[i+1] = temp;
exchange = true;
}
}
if (!exchange) return;
}
}
复制代码
冒泡排序包含两个操做:比较和交换。交换次数最好状况=0;最差状况=n*(n-1)/2,平均交换次数粗略来看是n*(n-1)/4,比较次数确定比交换次数多,所以在加上比较次数,因此平均复杂度大体是O(n2)。数组
思路:比较和插入性能优化
将数组分为两个区域:已排序区域和未排序区域。主要操做已排序区域,最初就是数组第一个元素时有序,其他无序;每次从无序区域拿一个元素和前面有序区域元素比较,再插入合适位置。bash
function insertSort(array) {
for (let i = 1; i < array.length; i++) {
let currentValue = array[i];
let j = i-1;
for (; j >= 0 ; j--) {
if (array[j] > currentValue) {
array[j+1] = array[j];
} else {
break;
}
}
array[j+1] = currentValue;
}
}
复制代码
最好的时间复杂度是彻底有序:O(n)性能
最坏的时间复杂度彻底逆序:O(n2)优化
平均时间复杂度:向数组插入一个元素的平均复杂度是O(n),而插入排序算法每一个元素都须要插入一次,所以是O(n2)ui
思路:查找和交换。同插入相似,分出已排序和未排序区间。可是选择排序主要操做未排序区域,每次从未排序区间找出最小元素,将其放在已排序区间的末尾。spa
function selectSort(array) {
for (let i = 0; i < array.length; i++) {
let currentMinnum = array[i];
let currentMinnumIndex = i;
for (let j = i + 1; j < array.length; j++) {
if (currentMinnum > array[j]) {
currentMinnum = array[j];
currentMinnumIndex = j;
}
}
let temp = array[currentMinnumIndex];
array[currentMinnumIndex] = array[i];
array[i] = temp;
}
}
复制代码
能够看出不管哪一种数据排序,时间复杂度都是同样的O(n2);3d
冒泡和插入排序时间复杂度、空间复杂度、稳定性都是同样的,可是为何说插入要比冒泡更好呢?主要是冒泡每次循环执行交换操做是3步,而插入仅是一步移动。所以当数据量比较大时,且但愿把性能优化到极致的话,首选插入排序。code
是否容许修改链表的节点value值,仍是只能改变节点的位置。通常而言,考虑只能改变节点位置,冒泡排序相比于数组实现,比较次数一致,但交换时操做更复杂;插入排序,比较次数一致,不须要再有后移操做,找到位置后能够直接插入,但排序完毕后可能须要倒置链表;选择排序比较次数一致,交换操做一样比较麻烦。综上,时间复杂度和空间复杂度并没有明显变化,若追求极致性能,冒泡排序的时间复杂度系数会变大,插入排序系数会减少,选择排序无明显变化。