冒泡排序
思路/原理:比较相邻的两个元素,如果前一个比后一个大,则交换位置,每一趟会将最小或最大的元素“浮”到顶端,最终达到完全有序。就好像一串气泡一样,最终从小到大或从大到小依次排下来。
function bubbleSort(arr) {
var len = arr.length;
// i表示第几趟排序
for(var i = 0; i < len - 1; i++) {
// j表示交换次数
for(var j = 0; j < len - 1 - i; j++) {
if(arr[j] > arr[j + 1]) {
// var temp = arr[j];
// arr[j] = arr[j + 1];
// arr[j + 1] = temp;
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
}
return arr;
}
console.log(bubbleSort([3, 1, 8, 10, 5]));时间复杂度: 平均情况O(n²) 最坏情况O(n²) 最好情况O(n)
空间复杂度: O(1)
稳定性: 稳定
由于冒泡排序只在相邻元素大小不符合要求时才调换他们的位置,它并不改变相同元素之间的相对顺序,因此它是稳定的排序算法。
复杂性: 简单
选择排序
思路/原理: 每一趟从待排序的记录中选出最小的元素,顺序放在已排好序的序列最后,直到全部记录排序完毕。
function selectSort(arr) {
var len = arr.length;
// 控制位置
for(var i = 0; i < len - 1; i++) {
// 假如这个是最小的
var min = i;
// 与后面的数字进行比较 寻找最小值的索引
for(var j = i + 1; j < len; j++) {
if(arr[j] < arr[min]) {
min = j;
}
}
// 如果当前的值的索引和最小值的索引不相等 交换位置
if(i !== min) {
[arr[i], arr[min]] = [arr[min], arr[i]];
}
}
return arr;
}时间复杂度: 平均情况O(n²) 最坏情况O(n²) 最好情况O(n²)
空间复杂度: O(1)
稳定性: 不稳定
插入排序
思路/原理: 将排序分为排序与未排序,将未排序的数依次向排序数进行比较。
function insertSort(arr) {
var len = arr.length;
for (var i = 1; i < len; i++) {
var temp = arr[i]; // 要插入的元素
// 与前面的排序好的数组进行比较
var j = i - 1;
while(j >= 0 && temp < arr[j]) {
// 如果当前元素小于他们 则他们往后运动 并交换当前元素和他们的位置 否则不动
arr[j + 1] = arr[j];
j --;
}
arr[j + 1] = temp;
}
return arr
}
console.log(insertSort([2, 1, 4, 8, 3])); 时间复杂度: 平均情况O(n²) 最坏情况O(n²) 最好情况O(n)
空间复杂度: O(1)
稳定性: 稳定
归并排序
思路/原理: 归并排序建立在归并操作之上 它采取分而治之的思想 将数组拆分为两个子数组 分别排序 最后才将两个子数组合并 拆分的两个子数组 再继续递归拆分为更小的子数组 进而分别排序 直到数组长度为1 直接返回该数组为止
// 采用分而治之的思想 把数组以递归的方式分为左右相等的两个数组
function mergeSort(arr) {
var len = arr.length;
// 递归出口
if(len < 2) {
return arr;
}
var mid = parseInt(len / 2),
left = arr.slice(0, mid),
right = arr.slice(mid);
return merge(mergeSort(left), mergeSort(right));
}
// 把两个数组进行排序
function merge(left, right) {
var res = [];
while(left.length && right.length) {
if(left[0] < right[0]) {
res.push(left.shift());
}else {
res.push(right.shift());
}
}
// 把剩余的数组连接
while(left.length) {
res.push(left.shift());
}
while(right.length) {
res.push(right.shift());
}
return res;
}时间复杂度: 平均情况O(n log n) 最坏情况O(n log n) 最好情况O(n log n)
空间复杂度: O(n)
稳定性: 稳定
快速排序
思路/原理: 在数据集之中 选择一个元素作为"基准"(pivot),所有小于"基准"的元素,都移到"基准"的左边,所有大于"基准"的元素,都移到"基准"的右边,对"基准"左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。
function quickSort(arr) {
if (arr.length <= 1) {
return arr;
}
var pivotIndex = Math.floor(arr.length / 2);
var pivot = arr.splice(pivotIndex, 1)[0];
var left = [];
var right = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i] < pivot) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
return quickSort(left).concat([pivot], quickSort(right));
}; 时间复杂度: 平均情况O(n log n) 最坏情况O(n²) 最好情况O(n log n)
空间复杂度: O(log n)
稳定性: 不稳定
堆排序
// 构建大顶堆
function heapify(arr, len, index) {
var largest = index,
left = index * 2 + 1,
right = index * 2 + 2;
if(left < len && arr[left] > arr[largest]) {
largest = left;
}
if(right < len && arr[right] > arr[largest]) {
largest = right;
}
// 交换 递归出口
if(largest !== index) {
[arr[index], arr[largest]] = [arr[largest], arr[index]];
// 重新调整下面的位置 构建大顶堆
heapify(arr, len, largest);
}
}
// 排序
function heapSort(arr) {
var len = arr.length;
// 从第一个非叶子节点开始构建大顶堆 从下往上 从右往左
for(var i = Math.floor(len / 2 - 1); i >= 0; i--) {
heapify(arr, len, i);
}
for(var i = len - 1; i >= 0; i--) {
// 把最大值压入最下面 位置交换
[arr[0], arr[i]] = [arr[i], arr[0]];
heapify(arr, i, 0);
}
return arr;
}时间复杂度: 平均情况O(n log n) 最坏情况O(n log n) 最好情况O(n log n)
空间复杂度: O(1)
稳定性: 不稳定
计数排序
function countSort(arr) {
var len = arr.length;
// 先找出最小值和最大值
var min = arr[0],
max = arr[0];
for(var i = 1; i < len; i++) {
if(arr[i] < min) {
min = arr[i];
}
if(arr[i] > max) {
max = arr[i];
}
}
// 计数数组的长度
var d = max - min + 1;
// 统计数次出现的次数
var countArr = [];
for(var i = 0; i < len; i++) {
if(!countArr[arr[i] - min]) {
countArr[arr[i] - min] = 1;
}else {
countArr[arr[i] - min] ++;
}
}
// 累加
var sum = 0;
for(var i = 0; i < d; i++) {
// 把undefined转化为0
if(!countArr[i]) {
countArr[i] = 0;
}
sum += countArr[i];
countArr[i] = sum;
}
console.log(countArr);
// 从统计数组最后一位向前递减
var newArr = [];
for(var i = len - 1; i>= 0; i--) {
newArr[ countArr[arr[i] - min] - 1 ] = arr[i];
countArr[arr[i] - min] --;
}
return newArr;
}时间复杂度: 平均情况O(n+k) 最坏情况O(n+k) 最好情况O(n+k)
空间复杂度: O(k)
稳定性: 稳定
计数排序的缺点:
上述缺点桶排序可以做出弥补
未完待续。。。。。。。。。。。。。。。。。。。。。。。。。
你的点赞是我持续输出的动力 希望能帮助到大家 互相学习 有任何问题下面留言 一定回复