前端算法总结
一、前端算法总结
1、排序
1.冒泡排序
冒泡排序就是重复“从序列右边开始比较相邻两个数字的大小,再根据结果交换两个数字的位置”这一操作的算法。在这个过程中,数字会像泡泡一样,慢慢从右往左“浮”到序列的顶端,所以这个算法才被称为“冒泡排序”。
第一轮,索引 len
和 len-1
比较,接着 len-1
和 len-2
比较,…直到索引 1
和 0
比较,比较了 len -2
次。
第二轮,索引 len
和 len-1
比较,接着 len-1
和 len-2
比较,…直到索引 2
和 1
比较,比较了 len -3
次。
…
第 len -2
轮,索引 len
和 len-1
比较,比较了 1
次。
最终比较 len-2
轮。
假设把它们放在数组里,这主要是提现算法思想
list = [5,3,8,4,2,1,9,7,6];
(function bubble(argu){
let len = argu.length, flag;//保存数组长度
for(let j = 0;j < len-1;j ++){
for(let i = len-1;i > j;i --){//最低索引1和0比较
if(argu[i] < argu[i - 1]){//这里升序/倒序通过><即可控制
flag = argu[i];
argu[i] = argu[i - 1];
argu[i - 1] = flag;
}
}
}
console.log(argu);
}(list));
冒泡排序的时间复杂度为 O(n^2)
。
2.选择排序
选择排序就是重复“从待排序的数据中寻找最小值,将其与序列最左边的数字进行交换”这一操作的算法。在序列中寻找最小值时使用的是线性查找。
前面一章提到了数组的查找方式:线性查找,从第一个开始找,直到找到目标。
function exchange(arr,c1,c2){//提前写好替换的方法
let temp = arr[c1];
arr[c1] = arr[c2];
arr[c2] = temp;
}
(function selectSort(arr){
let len = arr.length;
for(let i = 0;i < len- 1;i ++){//一个一个排,排到倒数第二位,最后一位也就确定了
let min = arr[i];//数组的线性查找,假设arr[i]是目标:最小值
let minIndex = i;
for(let j = i + 1;j < len;j ++){//拿后面一个索引值与当前比,所以j = i +1,但不能越界len
if(arr[j] < min){//如果当前值不是目标:最小值,就将最小值与当前值换位
min = arr[j];
minIndex = j;
}
}
exchange(arr,i,minIndex);
}
console.log(arr);
}([6,1,7,8,9,3,5,4,2]))
选择排序的时间复杂度也和冒泡排序的一样,都为 O(n^2)
。
3.插入排序
插入排序是一种从序列左端开始依次对数据进行排序的算法。在排序过程中,左侧的数据陆续归位,而右侧留下的就是还未被排序的数据。插入排序的思路就是从右侧的未排序区域内取出一个数据,然后将它插入到已排序区域内合适的位置上。
(function insertion(argu){
let len = argu.length, flag;
for(let j = 1;j < len;j ++){//从第二个开始与前面进行比较
for(let i = j-1;i >= 0;i --){//与前面的数一一比较
if(argu[i+1] < argu[i]){
flag = argu[i+1];
argu[i+1] = argu[i];
argu[i] = flag;
}
}
}
console.log(argu);
})([5,3,4,7,2,8,6,9,1]);
时间复杂度和冒泡排序的一样,都为 O(n^2)
。
4.归并算法
归并排序算法会把序列分成长度相同的两个子序列,当无法继续往下分时(也就是每个子序列中只有一个数据时),就对子序列进行归并。归并指的是把两个排好序的子序列合并成一个有序序列。
const arr = [6,3,7,4,5,1,2];
function merge(left, right) {
var tmp = [];
while (left.length && right.length) {
if (left[0] < right[0])
tmp.push(left.shift());
else
tmp.push(right.shift());
}
return tmp.concat(left, right);
}
function mergeSort(argu) {
if (argu.length === 1)
return argu;
var mid = Math.floor(argu.length / 2);
var left = argu.slice(0, mid);
var right = argu.slice(mid);
return merge(mergeSort(left), mergeSort(right));
};
console.log(mergeSort(arr));
总的运行时间为 O(nlogn)
,这与前面讲到的堆排序相同。
5.快速排序
快速排序算法首先会在序列中随机选择一个基准值(pivot),然后将除了基准值以外的数分为“比基准值小的数”和“比基准值大的数”这两个类别,再将其排列成以下形式。
//第一种方法
function quickSort(arr){
//如果数组<=1,则直接返回
if(arr.length<=1){return arr;}
//接下来就是设计找基准并比大小
var pivotIndex=Math.floor(arr.length/2);//数组长度/2取整
//找基准,并把基准从原数组删除
var pivot = arr.splice(pivotIndex,1)[0];
//定义左右数组
var left = [];
var right = [];
//比基准小的放在left,比基准大的放在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));
}
//第二种方法
function quickSort(arr) {
function _quickSort(left, right) {
if (left < 0 || right > arr.length - 1 || left >= right) {
return;//排除意外
}
let key = arr[right];//拿到基准数
let low = left, hight = right;
while (low < hight) {
while (arr[low] <= key && low < hight) {
low++;
}
arr[hight] = arr[low];//出现比key大的值,覆盖基准数
while (arr[hight] >= key && hight > low) {
hight--;
}
arr[low] = arr[hight];//出现比key小的值,覆盖
}
arr[low] = key;
//左边排
_quickSort(left, low - 1);
//右边排
_quickSort(hight + 1, right);
};
_quickSort(0, arr.length - 1)
}
整体的时间复杂度为 O(nlogn)
。
2、查找
1.线性查找
线性查找的操作很简单,只要在数组中从头开始依次往下查找即可。
实现方法就不多说了,循环判断都行。时间复杂度便为 O(n)
。
2.二分查找
二分查找通过比较数组中间的数据与目标数据的大小,可以得知目标数据是在数组的左边还是右边。
前面提到的快速排序,就用到了二分法的思想。时间复杂度为 O(logn)
。
3.插值查找
function interpolationSearch(arr, value) {
function _interpolationSearch(left, right) {
if (left === right) {
return arr[left] === value;
}
if (left > right || left < 0 || right > arr.length - 1) {
return false;
}
var mid = Math.floor(((value - arr[left]) / (arr[right] - arr[left])) * (right - left) + left);
if (mid < left || mid > right) {
return false;
}
if (arr[mid] === value) {
return true;
} else if (arr[mid] > value) {
//在左边继续寻找
return _interpolationSearch(left, mid - 1)
} else {//在右边继续寻找
return _interpolationSearch(mid + 1, right)
}
};
return _interpolationSearch(0, arr.length - 1);//要把里面返回的true或false返回给外界
};
3、搜索
1.广度优先搜索
广度优先搜索是一种对图进行搜索的算法。假设我们一开始位于某个顶点(即起点),此时并不知道图的整体结构,而我们的目的是从起点开始顺着边搜索,直到到达指定顶点(即终点)。
作为前端,我只是对其思想进行基本了解
广度优先搜索的特征为从起点开始,由近及远进行广泛的搜索。因此,目标顶点离
起点越近,搜索结束得就越快。
2.深度优先搜索
深度优先搜索和广度优先搜索一样,都是对图进行搜索的算法,目的也都是从起点开始搜索直到到达指定顶点(终点)。深度优先搜索会沿着一条路径不断往下搜索直到不能再继续为止,然后再折返,开始搜索下一条候补路径。
深度优先搜索选择的则是最新成为候补的顶点,所以会一路往下,沿着新发现的路径不断深入搜索。
4、安全
这里由于本博主前面已经了解过https协议,该模块相关知识请移步深入剖析https(协议)模块
5、网页排名
网页排名(PageRank,也叫作佩奇排名)是一种在搜索网页时对搜索结果进行排序的算法。Google 因在搜索引擎中使用了这个算法而成为了世界知名的大企业是众所周知的事情。
Google 公司提供了使用网页排名算法的搜索引擎,然后凭借其强大的性能成为了世界知名企业。当然,如今决定 Google 搜索结果排序的已不仅仅是网页排名这一个算法了。
博主开始运营自己的公众号啦,感兴趣的可以关注“飞羽逐星”微信公众号哦,拿起手机就能阅读感兴趣的文章啦!