const RED = true; const BLACK = false; // å®ä¹çº¢é»æ èç¹ class Node { constructor(key, value) { this.key = key; // é® this.value = value; // å¼ this.color = RED; // é¢è² this.left = null; // å·¦åèç¹ this.right = null; // å³åèç¹ } } module.exports = class RBTree { constructor() { this.root = null; this.size = 0; } // 夿èç¹nodeçé¢è² isRed(node) { if(node === null) return BLACK; return node.color; } // node x // / \ å·¦æè½¬ / \ // T1 x ----------------> node T3 // / \ / \ // T2 T3 T1 T2 leftRotate(node) { let x = node.right; // å·¦æè½¬ node.right = x.left; x.left = node; // æ´æ°é¢è²; x.color = node.color; node.color = RED; return x; } // node x // / \ å³æè½¬ / \ // x T2 ----------------> y node // / \ / \ // y T1 T1 T2 rightRotate(node) { let x = node.left; // å³æè½¬; node.left = x.right; x.right = node; // æ´æ°é¢è²; x.color = node.color; node.color = RED; return x; } // é¢è²ç¿»è½¬ flipColors(node) { node.color = RED; node.left.color = BLACK; node.right.color = BLACK; } // åäºåæç´¢æ 䏿·»å æ°çå ç´ (key, value) add(key, value) { this.root = this._add(this.root, key, value); this.root.color = BLACK; // æç»æ ¹èç¹ä¸ºé»è²èç¹ } // å以nodeä¸ºæ ¹çäºåæç´¢æ ä¸æå ¥å ç´ (key, value),éå½ç®æ³ // è¿åæå ¥æ°èç¹åçº¢é»æ çæ ¹ _add(node, key, value) { if(node === null) { this.size++; return new Node(key, value); // é»è®¤æå ¥çº¢è²èç¹ } if(key < node.key) { node.left = this._add(node.left, key, value); } else if(key > node.key) { node.right = this._add(node.right, key, value); } else { node.value = value; // æ´æ°å¼ } // å©ç¨åæº¯æ³æ´æ°é¢è² // é¢è²ååæ åµï¼ B -- é»è² R -- çº¢è² n -- null(å¶åèç¹) // 1. æå ¥'A' // A(B) // / \ // n(B) n(B) // // 2. æå ¥'F': éè¦åæ¢ï¼ä½¿ç¨æ¹æ³1忢 // A(B) F(B) // / \ å·¦æ / \ // n(B) F(R) -------> A(R) n(B) // / \ / \ // n(B) n(B) n(B) n(B) // // 3. æå ¥ 'M' // F(B) // / \ // A(R) M(R) // / \ / \ // n(B) n(B) n(B) n(B) // // 4. æå ¥ 'C': éè¦åæ¢ï¼ä½¿ç¨æ¹æ³1忢,ä¹ååç¨æ¹æ³2忢,æåï¼åç¨æ¹æ³3翻转é¢è²,æåæ ¹èç¹åæ¢ä¸ºé»è² // F(B) F(B) C(B) C(R) // / \ / \ / \ / \ // A(R) M(R) å·¦æ C(R) M(R) 峿 A(R) F(R) 翻转é¢è² A(B) F(B) // / \ / \ -------> / \ / \ --------> / \ / \ ---------> / \ / \ // n(B) C(R) n(B) n(B) A(R) n(B) n(B) n(B) n(B) n(B) n(B) M(R) n(B) n(B) n(B) M(R) // / \ / \ / \ / \ // n(B) n(B) n(B) n(B) n(B) n(B) n(B) n(B) // æ¹æ³1ï¼å¦æå½åèç¹çå³èç¹ä¸ºçº¢è²ï¼ä¸å·¦èç¹é红è²ï¼åè¿è¡å·¦æ if(this.isRed(node.right) && !this.isRed(node.left)) { node = this.leftRotate(node); } // æ¹æ³2ï¼å¦æå½åèç¹çå·¦èç¹å左左èç¹é½ä¸ºçº¢è²ï¼åè¿è¡å³æ if(this.isRed(node.left) && this.isRed(node.left.left)) { node = this.rightRotate(node); } // æ¹æ³3ï¼å¦æå½åèç¹å·¦å³åæ é½ä¸ºçº¢è²ï¼å翻转é¢è² if(this.isRed(node.left) && this.isRed(node.right)) this.flipColors(node); return node; } // è¿å以nodeä¸ºæ ¹èç¹çäºåæç´¢æ ä¸ï¼keyæå¨çèç¹ getNode(node, key) { if(node === null) { return null; } if(key === node.key) { return node; } else if(key < node.key) { return this.getNode(node.left, key); } else { return this.getNode(node.right, key); } } // 夿æ¯å å«è¯¥å¼ contains(key) { return this.getNode(this.root, key) !== null; } get(key) { let node = this.getNode(this.root, key); return node === null ? null : node.value; } set(key, value) { let node = this.getNode(this.root, key); if(node === null) { throw(key+" doesn't exist!"); } node.value = value; } // è¿å以nodeä¸ºæ ¹çäºåæç´¢æ çæå°å¼æå¨çèç¹ minimun(node) { if(node.left === null) return node; return this.minimun(node.left); } // å 餿以nodeä¸ºæ ¹çäºåæç´¢æ ä¸çæå°èç¹ // è¿åå é¤èç¹åæ°çäºåæç´¢æ çæ ¹ removeMin(node) { if(node.left === null) { let rightNode = node.right; node.right = null; this.size--; return rightNode; } node.left = this.removeMin(node.left); return node; } // ä»äºåæç´¢æ ä¸å é¤é®ä¸ºkeyçèç¹ remove(key) { let node = this.getNode(this.root, key); if(node !== null) { this.root = this._remove(this.root, key); return node.value; } return null; } _remove(node, key) { if(node === null) { return null; } if(key < node.key) { node.left = this._remove(node.left, key); return node; } else if(key > node.key) { node.right = this._remove(node.right, key); return node; } else { // å¾ å é¤èç¹å·¦åæ ä¸ºç©ºçæ åµ if(node.left === null) { let rightNode = node.right; node.right = null; this.size--; return rightNode; } // å¾ å é¤èç¹å³åæ ä¸ºç©ºçæ åµ if(node.right === null) { let leftNode = node.left; node.left = null; this.size--; return leftNode; } // å¾ å é¤èç¹å·¦å³åæ åä¸ä¸ºç©ºçæ åµ // æ¾å°æ¯å¾ å é¤èç¹å¤§çæå°èç¹ï¼å³å¾ å é¤èç¹å³åæ çæå°èç¹ // ç¨è¿ä¸ªèç¹é¡¶æ¿å¾ å é¤èç¹çä½ç½® let successor = this.minimun(node.right); successor.right = this.removeMin(node.right); successor.left = node.left; node.left = node.right = null; return successor; } } // è¿åsize getSize() { return this.size; } // 夿æ¯å¦ä¸ºç©º isEmpty() { return this.size === 0; } }