此文章将会持续更新-
二叉树
特点:每个树最多有两个子树的树形结构,一颗二叉树通常有根节点,分支节点,叶子节点组成,每个分支节点也被称为一颗子树,子树又被称为“左子树”和右子树
- 跟节点:二叉树最顶层节点
- 分支节点:除了根节点以外拥有叶子节点
- 叶子节点:除了自身,没有其他子节点
二叉搜索树
// 节点
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;