树数据结构:树是一种分层数据的数据模型
树数据结构理解:位于树顶部的节点叫做根节点.它没有父节点.树中的每个元素都叫做节点,节点分为内部节点和外部节点.至少有一个子节点的节点称为内部节点.没有子元素的节点称为外部节点或叶节点.
二叉树和二叉搜索树:二叉树中的节点最多只能有两个子节点:一个是左侧子节点,另一个是右侧子节点.二叉搜索树是二叉树的一种.但是只允许你在左侧节点存储(比父节点)小的值,在右侧节点存储(比父节点)大的值.
个人理解:和链表一样我们将通过指针(引用)来表示节点之间的关系.在双向链表中,每个节点包含两个指针,一个指向下一个节点,另一个指向上一个节点.对于树,使用同样的方式(也是用两个指针),一个指向左侧子节点,另一个指向右侧子节点
实现一个二叉搜索树
class BinarySearchTree{ constructor(compareFn = defaultCompare){ this.root = null this.compareFn = compareFn } }
先创建一个二叉搜索树节点
class Node{ constructor(key){ this.key = key this.left = null this.right = null } }
实现一个insertNode方法
BinarySearchTree.prototype.insertNode = function(node,key){ if(this.compareFn(node.key,key)===Compare.LESS_THAN){ if(node.left == null){ node.left = new Node(key) }else{ this.insertNode(node.left,key) } }else{ if(node.right == null){ node.right = new Node(key) }else{ this.insertNode(node.right,key) } } }
实现一个insert方法
BinarySearchTree.prototype.insert = function(key){ if(this.root==null){ this.root = new Node(key) }else{ this.insertNode(this.root,key) } }
定义一个回调函数
function cnFn(param){ console.log(param) }
中序遍历:是一种上行顺序访问BST所有节点的遍历方式,也就是以从最小到最大的顺序访问所有节点,中序遍历的一种应用就是对树进行排序操作
BinarySearchTree.prototype.inOrderTraverse = function(cb){ this.inOrderTraverseNode(this.root,cb) } BinarySearchTree.prototype.inOrderTraverseNode = function(node,cb){ if(node!=null){ this.inOrderTraverseNode(node.left,cb) cb(node.key) this.inOrderTraverseNode(node.right,cb) } }
先序遍历:是以优先于后代节点的顺序访问每个节点。先序遍历的一种应用是打印一个结构化文档
BinarySearchTree.prototype.preOrderTraverse = function(cb){ this.preOrderTraverseNode(this.root,cb) } BinarySearchTree.prototype.preOrderTraverseNode = function(node,cb){ if(node!=null){ cb(node.key) this.preOrderTraverseNode(node.left,cb) this.preOrderTraverseNode(node.right,cb) } }
后序遍历:是先访问节点的后代节点在访问节点本身。后序遍历的一种应用是计算一个目录及其子目录中所有文件所占空间的小
BinarySearchTree.prototype.postOrderTraverse = function(cb){ this.postOrderTraverseNode(this.root,cb) } BinarySearchTree.prototype.postOrderTraverseNode = function(node,cb){ if(node!=null){ this.postOrderTraverseNode(node.left,cb) this.postOrderTraverseNode(node.right,cb) cb(node.key) } }
/**
* 搜索树中的值
* 搜索最小值和最大值
* 先实现获取到最小与最大节点,再使用min、max方法调用
*/
BinarySearchTree.prototype.minNode = function(node){ let current = node while(current!=null&¤t.left!=null){ current = current.left } return current } BinarySearchTree.prototype.maxNode = function(node){ let current = node while(current!=null&¤t.right!=null){ current = current.right } return current } BinarySearchTree.prototype.min = function(){ return this.minNode(this.root) } BinarySearchTree.prototype.max = function(){ return this.maxNode(this.root) }
/**
* 先实现一个searchNode方法
*/
BinarySearchTree.prototype.searchNode = function(node,key){ if(node==null){ return false } if(this.compareFn(key,node.key) === Compare.LESS_THAN){ return this.searchNode(node.left,key) }else if(this.compareFn(key,node.key) === Compare.BIGGER_THAN){ return this.searchNode(node.right,key) }else{ return true } }
/**
* 搜索一个特定的值;返回值:布尔值
*/
BinarySearchTree.prototype.search = function(key){ return this.searchNode(this.root,key) }
/**
* 先实现一个removeNode方法;返回值:一个node节点对象
*/
BinarySearchTree.prototype.removeNode = function(node,key){ if(node==null){ return null } if(this.compareFn(key,node.key) === Compare.LESS_THAN){ node.left = this.removeNode(node.left,key) return node }else if(this.compareFn(key,node.key) === Compare.BIGGER_THAN){ node.right = this.removeNode(node.right,key) return node }else{ if(node.left == null && node.right == null){ node = null return node } if(node.left == null){ node = node.right return node }else if(node.right == null){ node = node.left return node } let min = this.minNode(node.right) node.key = min.key node.right = this.removeNode(node.right,min.key) return node } }
/**
* 移除一个节点
*/
BinarySearchTree.prototype.remove = function(key){ this.root = this.removeNode(this.root,key) }
AVL & 红黑树
未完待续...