const Compare ={
LESS_THAN:-1,
BIGGER_THAN:1,
EQUALS:0
}
const BalancedFactor = {
UNBALANCED_LEFT:1,
SLIGHTLY_UNBALANCED_LEFT:2,
BALANCED:3,
UNBALANCED_RIGHT:4,
SLIGHTLY_UNBALANCED_RIGHT:5
}
function defaultCompare(a,b){
return a === b ? Compare.EQUALS:(a<b)?Compare.LESS_THAN:Compare.BIGGER_THAN;
}
class Node{
constructor(key){
this.key = key;
this.left = null;
this.right = null;
}
}
class BinarySearchTree{
constructor(compareFn = defaultCompare){
this.root = null;
this.compareFn = compareFn;
}
insert(key){
this.root = this.insertNode(this.root,key);
}
insertNode(node,key){
if(node == null){
return new Node(key);
}
if(this.compareFn(key,node.key) === Compare.LESS_THAN){
node.left = this.insertNode(node.left,key);
}
else if(this.compareFn(key,node.key) === Compare.BIGGER_THAN){
node.right = this.insertNode(node.right,key);
}else{
return node;
}
return node;
}
search(key){
return this.searchNode(this.root,key);
}
searchNode(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;
}
}
remove(key){
this.root = this.removeNode(this.root,key);
}
removeNode(node,key){
if(node == null){
return node;
}
if(this.compareFn(key,node.key) === Compare.LESS_THAN){
node.left = this.removeNode(node.left,key);
}else if(this.compareFn(key,node.key) === Compare.BIGGER_THAN){
node.right = this.removeNode(node.right,key);
}else{
if(node.left == null && node.right == null){
node = null;
return node;
}
if(node.left == null){
node = node.right;
return node;
}
if(node.right == null){
node = node.left;
return node;
}
let aux = this.minNode(node.right);
node.key = aux.key;
node = this.removeNode(node.right,aux.key);
return node;
}
return node;
}
min(){
return this.minNode(this.root);;
}
minNode(node){
if(node == null){
return node;
}
while(node.left!=null){
node = node.left;
}
return node;
}
max(){
return this.maxNode(this.root);
}
maxNode(){
if(node == null){
return node;
}
while(node.right != null){
node = node.right;
}
return node;
}
inOrderTraverse(callback){
this.inOrderTraverseNode(this.root,callback);
}
inOrderTraverseNode(node,callback){
if(node == null)return;
this.inOrderTraverseNode(node.left,callback);
callback(node.key);
this.inOrderTraverseNode(node.right,callback);
}
inPostTraverse(callback){
this.inPostTraverseNode(this.root,callback);
}
inPostTraverseNode(node,callback){
if(node == null)return;
this.inPostTraverseNode(node.left,callback);
this.inPostTraverseNode(node.right,callback);
callback(node.key);
}
inPreTraverse(callback){
this.inPreTraverseNode(this.root,callback);
}
inPreTraverseNode(node,callback){
if(node == null){
return;
}
callback(node.key);
this.inPreTraverseNode(node.left,callback);
this.inPreTraverseNode(node.right,callback);
}
}
class AVLTree extends BinarySearchTree{
constructor(compareFn = defaultCompare){
super(compareFn);
}
insert(key){
this.root = this.insertNode(this.root,key);
}
insertNode(node,key){
if(node == null){
return new Node(key);
}
if(this.compareFn(key,node.key) === Compare.LESS_THAN){
node.left = this.insertNode(node.left,key);
}else if(this.compareFn(key,node.key) === Compare.BIGGER_THAN){
node.right = this.insertNode(node.right,key);
}else{
return node;
}
const balancedFactor = this.getBalanceFactor(node);
if(balancedFactor === BalancedFactor.UNBALANCED_LEFT){
if(this.compareFn(key,node.key) === Compare.LESS_THAN){
node = this.rotationLL(node);
}else{
node = this.rotationLR(node.left);
}
}
if(balancedFactor === BalancedFactor.UNBALANCED_RIGHT){
if(this.compareFn(key,node.key) === Compare.BIGGER_THAN){
node = this.rotationRR(node);
}else{
node = this.rotationRL(node.right);
}
}
return node;
}
remove(key){
this.root = this.removeNode(this.root,key);
}
removeNode(node,key){
node = super.removeNode(node,key);
if(node == null){
return node;
}
if(this.compareFn(key,node.key) === Compare.LESS_THAN){
node.left = this.removeNode(node.left,key);
}else if(this.compareFn(key,node.key) === Compare.BIGGER_THAN){
node.right = this.removeNode(node.right,key);
}else{
return node;
}
const balancedFactor = this.getBalanceFactor(node);
if(balancedFactor == BalancedFactor.UNBALANCED_LEFT){
const leftBalancedFactor = this.getBalanceFactor(node.left);
if(leftBalancedFactor == BalancedFactor.BALANCED|| leftBalancedFactor == BalancedFactor.SLIGHTLY_UNBALANCED_LEFT){
node = this.rotationLL(node);
}
if(leftBalancedFactor == BalancedFactor.SLIGHTLY_UNBALANCED_RIGHT){
node = this.rotationLR(node.left);
}
}
if(balancedFactor == BalancedFactor.UNBALANCED_RIGHT){
const rightBalancedFactor = this.getBalanceFactor(node.right);
if(rightBalancedFactor == BalancedFactor.BALANCED || rightBalancedFactor == BalancedFactor.SLIGHTLY_UNBALANCED_RIGHT){
node = this.rotationRR(node);
}
if(rightBalancedFactor == BalancedFactor.SLIGHTLY_UNBALANCED_RIGHT){
node = this.rotationRL(node.right);
}
}
return node;
}
rotationLL(node){
let tmp = node.left;
node.left =tmp.right;
tmp.right = node;
return tmp;
}
rotationRR(node){
let tmp = node.right;
node.right = tmp.left;
tmp.left = node;
return tmp;
}
rotationLR(node){
node.left = this.rotationLL(node.left);
return this.rotationRR(node);
}
rotationRL(node){
node.right = this.rotationRR(node.right);
return this.rotationLL(node);
}
getBalanceFactor(node){
if(node == null){
return;
}
let balanceFactor = this.getDifferenceHeight(node.left) - this.getDifferenceHeight(node.right);
switch(balanceFactor){
case 1:
return BalancedFactor.SLIGHTLY_UNBALANCED_LEFT;
case 2:
return BalancedFactor.UNBALANCED_LEFT;
case -1:
return BalancedFactor.SLIGHTLY_UNBALANCED_RIGHT;
case -2:
return BalancedFactor.UNBALANCED_RIGHT;
default:
return BalancedFactor.BALANCED;
}
}
getDifferenceHeight(node){
if(node == null){
return -1;
}
return Math.max(this.getDifferenceHeight(node.left),this.getDifferenceHeight(node.right))+1;
}
}
printNode = (value)=>console.log(value);
class RedBlackNode extends Node{
constructor(key){
super(key);
this.key = key;
this.color = Colors.RED;
this.parent = null;
}
isRed(){
return this.color === Colors.RED;
}
}
const Colors ={
RED:0,
BLACK:1
}
class RedBlackTree extends BinarySearchTree{
constructor(compareFn = defaultCompare){
super(compareFn);
this.compareFn = compareFn;
this.root = null;
}
insert(key){
if(this.root == null){
this.root = new RedBlackNode(key);
this.root.color = Colors.BLACK;
}else{
const newNode = this.insertNode(this.root,key);
this.fixTreeProperties(newNode);
}
}
insertNode(node,key){
if(this.compareFn(key,node.key) === Compare.LESS_THAN){
if(node.left == null){
node.left = new RedBlackNode(key);
node.left.parent = node;
return node.left;//返回当前的节点
}else{
return this.insertNode(node.left,key);
}
}
else{
if(node.right == null){
node.right = new RedBlackNode(key);
node.right.parent = node;
return node.right;
}else{
return this.insertNode(node.right,key);
}
}
}
fixTreeProperties(node){
//判断新节点,和新节点的父节点存不存在,以及父节点是否为红色,新节点是否为红色
while(node&&node.parent&&node.parent.color == Colors.RED && node.color != Colors.BLACK ){
let parent = node.parent;//获取父节点
const grandParent = parent.parent;//获取祖节点
//如果父节点是祖节点的左子节点
if(grandParent && grandParent.left == parent){
//获取叔节点
const uncle = grandParent.right;
//如果叔节点存在,并且叔节点的颜色是红色
if(uncle && uncle.color == Colors.RED){
grandParent.color = Colors.RED;
parent.color = Colors.BLACK;
uncle.color = Colors.BLACK;
node = grandParent;
}else{//如果叔节点的颜色为黑色
//新节点位于父节点的右边
if(node == parent.right){
this.rotationRR(parent);
node = parent;
parent = node.parent;
}
//新节点位于父节点的左边
this.rotationLL(grandParent);
parent.color = Colors.BLACK;//parent现在是祖节点
grandParent.color = Colors.RED;
node = parent;
}
}else{
const uncle = grandParent.left;
if(uncle && uncle.color !== Colors.BLACK){
grandParent.color = Colors.RED;
parent.color = Colors.BLACK;
uncle.color = Colors.BLACK;
node = grandParent;
}else{
if(node == parent.left){
this.rotationLL(parent);
node = parent;
parent = node.parent;
}
this.rotationRR(grandParent);
parent.color = Colors.BLACK;
grandParent.color = Colors.RED;
node = parent;
}
}
}
this.root.color = Colors.BLACK;
}
rotationLL(node){
//获取父节点的左子节点
const tmp = node.left;
//父节点的左子节点指向tmp的右子节点
node.left = tmp.right;
//如果tmp的左子节点存在
if(tmp.right && tmp.right.key){
//tmp的右子节点的父亲指向父节点
tmp.right.parent = node;
}
//tmp指向父节点的父亲;
tmp.parent = node.parent;
if(!node.parent){
this.root = tmp;
}else{
//判断父节点是祖节点的左节点还是右节点
if(node == node.parent.left){
//祖节点的左子节点是tmp
node.parent.left = tmp;
}else{
node.parent.right = tmp;
}
}
//父节点成为tmp的右子节点
tmp.right = node;
//父节点的父亲是tmp
node.parent = tmp;
}
rotationRR(node){
const tmp = node.right;
node.right = tmp.left;
if(tmp.left && tmp.left.key){
tmp.left.parent = node;
}
tmp.parent = node.parent;
if(!node.parent){
this.root = tmp;
}else{
if(node == node.parent.left){
node.parent.left = tmp;
}else{
node.parent.right = tmp;
}
}
tmp.left = node;
node.parent = tmp;
}
}