前端高频笔试

218 阅读3分钟

此文章将会持续更新-

二叉树

特点:每个树最多有两个子树的树形结构,一颗二叉树通常有根节点,分支节点,叶子节点组成,每个分支节点也被称为一颗子树,子树又被称为“左子树”和右子树

  • 跟节点:二叉树最顶层节点
  • 分支节点:除了根节点以外拥有叶子节点
  • 叶子节点:除了自身,没有其他子节点

二叉搜索树

// 节点
class TreeNode{
    constructor(element,parent){
        this.parent = parent; // 父节点
        this.element = element; // 当前节点
        this.left = null; // 左子节点
        this.right = null; // 右子节点
    }
}

// BST树
class TreeBST {
    constructor(){
        this.root = null; // 跟节点
        this.size = 0; // 共有多少个节点
    }
    add(element){ // 添加元素
        if(this.root == null){ // 如果为空则是根节点
            this.root = new TreeNode(element,null);
            this.size++;
            return;
        }
        let currentNode = this.root; // 当前跟节点
        let parent = null; // 存放上一次的值
        let compare = null; // 判断是左树还是右树
        while(currentNode){ // currentNode为null的时候代表是最后一个,往这个里面插入节点
            parent = currentNode;
            compare = element - currentNode.element;
            if(compare>0){
                currentNode = currentNode.right
            } else if(compare<0){
                currentNode = currentNode.left
            }
        }
        this.size++;
        let newTreeNode = new TreeNode(element,parent)
        if(compare>0){
            parent.right=newTreeNode
        } else if(compare<0){
            parent.left=newTreeNode
        }
    }
    // 树的遍历:1.前序,2,中序,3,后续,4,层级
    // 前序(根节点,左子树,右子树)
    preorderTraversal(){
    	const traversal = (node) => {
            if(this.root == null) return;
            console.log(node.element);
            traversal(node.left);
            traversal(node.right);
        }
        traversal(this.root);
    }
    // 中序 (先遍历左子树,根节点,右子树)
    inorderTraversal(){
       	const traversal = (node) => {
            if(this.root == null) return;
            traversal(node.left);
            console.log(node.element);
            traversal(node.right);
        }
        traversal(this.root);
    }
    // 后续 (先遍历左子树,右子树,跟节点)
    postorderTraversal(){
     	const traversal = (node) => {
            if(this.root == null) return;
            traversal(node.left);
            traversal(node.right);
            console.log(node.element);
        }
        traversal(this.root);
    }
    // 层级遍历 (从上往下,从左往右)
    levelOrderTraversal(){
      if(this.root==null) return;
      let currentNode = null;
      let index = 0;
      let stack = [this.root]
      while(currentNode = stack[index++]){
        console.log('---',currentNode.element)
      	if(currentNode.left){
            stack.push(currentNode.left)
        }
        if(currentNode.right){
            stack.push(currentNode.right)
        }
      }
    }
    // 翻转二叉树
    invertTree(){
       const traversal = (node) =>{
       	if(!node) return;
       	let lefttemp = node.left;
        let righttemp = node.right;
        node.left=righttemp;
        node.right=lefttemp;
        traversal(lefttemp)
        traversal(righttemp)
       }
       traversal(this.root);
    }
}

let newbst = new TreeBST()

let newarr = [8,10,2,6,12,16,14,1]

newarr.forEach(item=>{
    newbst.add(item)
})
console.dir(newbst,{depth:10})
// bst.preorderTraversal()
// bst.levelOrderTraversal()
bst.invertTree()

函数颗粒化 add(1)(2)(3,4); //10

	
function add(){
    let arr = Array.from(arguments)
    let temp = function(){
      let ar1 = Array.from(arguments);
      return add(...arr.concat(ar1))
    }
    temp.toString=function(){
        return arr.reduce((v1,v2)=>{
         return v1+v2;
     })
    }
    return temp;
 }
     
     
 console.log(add(1)(2)(3,4).toString())

链表

链表:线性表的链式存储结构。

单向链表:各个节点数据通过指针的方法串联起来,构成链表。

class Node(){
    constructor(element,next){
    	this.element = element; // 当前节点
        this.next = next; // 当前节点的下一个节点
    }
}

class LinkList{
    constructor(){
    	this.head = null; //指针
        this.size = 0; //链表的长度
    }
    add(index,element){
    	if(arguments.length==1){
        	element=index;
            index=this.size
        }
        if(index<0||index>this.size) throw new Error('索引异常')
        if(index==0){
          let head = this.head;
          this.ead = new Node(element,head)
        }else{
          // 获取当前索引的上一个和上一个的下一个,在中间插入当前索引
          let prevNode = this.getNode(index-1);// 当前索引的上一个
          let newNode = new Node(element,prevNode.next);
          prevNode.next = newNode;
        }
        this.size++;
    }
    remove(index){
    	if(this.size ==0 ) return;
        let oldNode; //存储要删除的节点
        if(index==0){
        	oldNode = this.head;
            this.head = oldNode&&oldNode.next;
        }else{
        	let currentNode = this.getNode(index-1); //删除节点的上一个节点
            oldNode = currentNode.next;
            currentNode.next = oldNode.next;
        }
        this.size--;
        return oldNode;
    }
    getNode(index){
     let current = this.head;
     for(let i=0;i<index;i++){
     	current = current.next
     }
     return current;
    }
    //翻转( 300 200 100到 100 200 300 )
    reverseLinkedList(){
    	let head = this.head;
        if(head==null||head.next==null)return;
        let newhead =null;
        while(head!=null){
        	let  temp = head.next; // 200
            head = newhead;
            newhead = head;
            head = temp;
        }
    }
}
ll.add(0,100)
ll.add(0,200)
ll.add(0,300)
console.dir(ll.head,{depth:10})

node内置events模块(on,off,emit,once,newlist),自己实现的一个发布订阅模式

调用部分

// const EventEmitter = require('events');
const EventEmitter = require('./eventsemmitter');

// console.log('EventEmitter',EventEmitter)
function Son(){}

Son.prototype.__proto__ = EventEmitter.prototype; // 继承EventEmitter原型上的方法

let son = new Son();

// console.log(son.on)

son.on('newListener',(e)=>{
    console.log('e---',e)
})

son.on('a',()=>{
    console.log('--a')
})
son.on('a',(...arg)=>{
    console.log('--a2',...arg)
})

let eat = (a)=>{
    console.log('--a3--',a)
}
// son.once('a',eat) // 只绑定一次
son.on('a',eat)

// son.off('a',eat); // 关闭
// son.emit('a',1,2,3);
son.emit('a',1,2,3);

实现部分

function EventEmitter(){
    this._events = {}
}
// 订阅
EventEmitter.prototype.on = function(name,callback){
    if(!this._events){
        this._events={}
    }

    if(name!=='newListener'){
        this.emit('newListener',name)
    }

    if(this._events[name]){
        this._events[name].push(callback)
    }else{
        this._events[name]=[callback]
    }
}
// 只绑定一次
EventEmitter.prototype.once = function(name,callback){
    let once = (...arg)=>{
        callback(...arg)
        this.off(name,once)
    }
    once.v = callback; // 记录当前的callback是哪个once的,在删除的时候也要删除对应的once绑定的事件
    this.on(name,once)
}
// 发布
EventEmitter.prototype.emit = function(name,...arg){
    if(!this._events[name]) return;
    if(this._events[name]){
        this._events[name].forEach((val)=>val(...arg))
    }
}
// 删除
EventEmitter.prototype.off = function(name,callback){
    if(!this._events[name]) return;
    
    this._events[name]=this._events[name].filter((val)=>{
        return val!==callback&&val.v!==callback
    })
}


module.exports = EventEmitter;