持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第 15 天,点击查看活动详情
常见的前端算法
冒泡排序,二叉树遍历,最长回文,二分查找,指针,链表等,堆栈,队列
数据结构
逻辑结构:集合、线性、树形、图形结构
物理结构:顺序、链式存储结构
冒泡排序
冒泡排序算法的原理如下:
比较相邻的元素。如果第一个比第二个大,就交换他们两个。
对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
针对所有的元素重复以上的步骤,除了最后一个。
持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比比较
// 编写方法,实现冒泡
var arr = [29,45,51,68,72,97];
// 外层循环,控制趟数,每一次找到一个最大值
for (var i = 0; i < arr.length - 1; i++) {
// 内层循环,控制比较的次数,并且判断两个数的大小
for (var j = 0; j < arr.length - 1 - i; j++) {
// 白话解释:如果前面的数大,放到后面(当然是从小到大的冒泡排序)
if (arr[j] > arr[j + 1]) {
var temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
console.log(arr); // [2, 4, 5, 12, 31, 32, 45, 52, 78, 89]
数组去重
利用ES6的Set数据结构的特性
let arr = [1,1,'true','true',true,true,15,15,false,false,undefined,undefined, null,null, NaN, NaN,'NaN','NaN', 0, 0, 'a', 'a',{},{}];
function distinct(arr) {
return Array.from(new Set(arr))
}
function distinct(arr) {
return [...new Set(arr)]
}
console.log(distinct(arr)) // [1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}, {…}]
防抖和节流
防抖(debounce)
所谓防抖,就是指触发事件后n秒内函数只能执行一次,如果在n秒内再次触发了事件,则会重新计算函数执行时间。
非立即执行版
function debounce(func, wait) {
let timeout;
return function () {
let context = this;
let args = arguments;
if (timeout) clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(context, args)
}, wait);
}
}
立即执行版本
function debounce(func,wait) {
let timeout;
return function () {
let context = this;
let args = arguments;
if (timeout) clearTimeout(timeout);
let callNow = !timeout;
timeout = setTimeout(() => {
timeout = null;
}, wait)
if (callNow) func.apply(context, args)
}
}
双剑合璧版
/**
* @desc 函数防抖
* @param func 函数
* @param wait 延迟执行毫秒数
* @param immediate true 表立即执行,false 表非立即执行
*/
function debounce(func,wait,immediate) {
let timeout;
return function () {
let context = this;
let args = arguments;
if (timeout) clearTimeout(timeout);
if (immediate) {
var callNow = !timeout;
timeout = setTimeout(() => {
timeout = null;
}, wait)
if (callNow) func.apply(context, args)
}
else {
timeout = setTimeout(function(){
func.apply(context, args)
}, wait);
}
}
}
节流 (throttle)
节流,就是指连续触发事件在n秒中只执行一次函数,节流会稀释函数的执行频率。
时间戳版本
function throttle(func, wait) {
let previous = 0;
return function() {
let now = Date.now();
let context = this;
let args = arguments;
if (now - previous > wait) {
func.apply(context, args);
previous = now;
}
}
}
定时器版本
function throttle(func, wait) {
let timeout;
return function() {
let context = this;
let args = arguments;
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
func.apply(context, args)
}, wait)
}
}
}
双剑合璧版
/**
* @desc 函数节流
* @param func 函数
* @param wait 延迟执行毫秒数
* @param type 1 表时间戳版,2 表定时器版
*/
function throttle(func, wait ,type) {
if(type===1){
let previous = 0;
}else if(type===2){
let timeout;
}
return function() {
let context = this;
let args = arguments;
if(type===1){
let now = Date.now();
if (now - previous > wait) {
func.apply(context, args);
previous = now;
}
}else if(type===2){
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
func.apply(context, args)
}, wait)
}
}
}
}
快速排序
// 快排
function quickSort(arr, i, j) {
if(i < j) {
let left = i;
let right = j;
let pivot = arr[left];
while(i < j) {
while(arr[j] >= pivot && i < j) { // 从后往前找比基准小的数
j--;
}
if(i < j) {
arr[i++] = arr[j];
}
while(arr[i] <= pivot && i < j) { // 从前往后找比基准大的数
i++;
}
if(i < j) {
arr[j--] = arr[i];
}
}
arr[i] = pivot;
quickSort(arr, left, i-1);
quickSort(arr, i+1, right);
return arr;
}
}
// example
let arr = [2, 10, 4, 1, 0, 9, 5 ,2];
console.log(quickSort(arr, 0 , arr.length-1));
function quickSort(arr, i, j) {
if(i < j) {
let left = i;
let right = j;
let mid = Math.floor((left+right)/2);
let temp = arr[left];
arr[left] = arr[mid];
arr[mid] = temp;
let pivot = arr[left];
while(i < j) {
while(arr[j] >= pivot && i < j) { // 从后往前找比基准小的数
j--;
}
if(i < j) {
arr[i++] = arr[j];
}
while(arr[i] <= pivot && i < j) { // 从前往后找比基准大的数
i++;
}
if(i < j) {
arr[j--] = arr[i];
}
}
arr[i] = pivot;
quickSort(arr, left, i-1);
quickSort(arr, i+1, right);
return arr;
}
}
随机颜色
// 随机颜色,十六进制方法;
function getRandomColor( ) {
var rand = Math.floor(Math.random( ) * 0xFFFFFF).toString(16);
if(rand.length == 6){
return rand;
}else{
return getRandomColor();
}
}
打乱数组随机输出
var a = [1,2,3,4,5,6,7,8,9]
function randomSort(arr) {
return arr.sort((a, b) => {
return Math.random() > 0.5 ? 1 : -1;
})
}
randomSort(a)
合并两个升序数组为一个升序数组
var a=[1,3,4,5,7,8,9];
var b=[3,4,5,6,7,8,9];
var c= a.concat(b);
console.log(c);
for(var i=0;i<c.length;i++){
for(var j=i+1;j<c.length;j++){
if(c[i]==c[j]){
c.splice(j,1);
j--;
}
}
}
console.log(c);
c.sort();
console.log(c);
输入一个链表,反转链表后,输出新链表的表头
function reverseList(pHead) {
// 缓存传入的 pHead,创建一个空数组接收链表的值
var node = pHead, arr = [];
// 当节点不为空时,依次将节点值传入数组
while(node != null) {
arr.push(node.val);
node = node.next;
}
// 上面循环结束后 node 是表尾,需要重新定义表头
node = pHead;
// 将数组中的值 pop 出来依次赋给节点
while(node != null) {
node.val = arr.pop();
node = node.next;
}
return pHead;
}
反转二叉树
// 方法 一
var invertTree = function (root) {
if (root !== null) {
var temp = root.left;
root.left = root.right;
root.right = temp;
invertTree(root.left);
invertTree(root.right);
}
return root;
}
// 方法 二
var invertTree = function (root) {
if (root !== null) {
[root.left, root.right] = [invertTree(root.right), invertTree(root.left)]
}
return root;
}
统计HTML标签中以b开头的标签数量
const tags = document.getElementsByTagName('*');
// 要使用数组的方法必须将类数组转为真正的数组
const value = [...tags].filter((item) => item.tagName.startsWith('B'))
统计HTML标签中出现次数最多的标签
const tags = document.getElementsByTagName('*');
let map = new Map();
let maxStr = '';
let max = 0;
// 只是使用下标来获取,没有使用数组的方法,所以不需要将类数组转为数组
for(let i = 0; i < tags.length; i++) {
let value = map.get(tags[i].tagName)
if(value) {
map.set(tags[i].tagName, ++value)
} else {
map.set(tags[i].tagName, 1);
}
if(value > max) {
maxStr = tags[i].tagName;
max = value;
}
}
console.log(`当前最多的标签为 ${maxStr},个数为 ${max}` );