289 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
			
		
		
	
	
			289 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
| /*
 | |
| 文件名:RedBlackTreeClass.nut
 | |
| 路径:Dps_A/BaseClass/RedBlackTreeClass/RedBlackTreeClass.nut
 | |
| 创建日期:2024-09-19	12:42
 | |
| 文件用途:红黑树类
 | |
| */
 | |
| // 红黑树节点类
 | |
| class RBTreeNode {
 | |
|     key = null;
 | |
|     time = null;
 | |
|     left = null;
 | |
|     right = null;
 | |
|     parent = null;
 | |
|     color = null;
 | |
|     Info = null;
 | |
|     constructor(key, func_info) {
 | |
|         this.key = key;
 | |
|         this.time = key;
 | |
|         this.Info = func_info;
 | |
|         this.left = null;
 | |
|         this.right = null;
 | |
|         this.parent = null;
 | |
|         this.color = "red";
 | |
|     }
 | |
| 
 | |
|     function _tyoeof() {
 | |
|         return "RBTreeNode";
 | |
|     }
 | |
| }
 | |
| 
 | |
| // 红黑树类
 | |
| class RedBlackTree {
 | |
|     nil = null;
 | |
|     root = null;
 | |
|     size = 0;
 | |
| 
 | |
|     function _tyoeof() {
 | |
|         return "RedBlackTree";
 | |
|     }
 | |
| 
 | |
|     constructor() {
 | |
|         this.nil = RBTreeNode(null, null);
 | |
|         this.root = this.nil;
 | |
|     }
 | |
| 
 | |
|     function insert(key, func_info) {
 | |
|         local z = RBTreeNode(key, func_info);
 | |
|         local y = this.nil;
 | |
|         local x = this.root;
 | |
|         while (x != this.nil) {
 | |
|             y = x;
 | |
|             if (z.key< x.key) {
 | |
|                 x = x.left;
 | |
|             } else {
 | |
|                 x = x.right;
 | |
|             }
 | |
|         }
 | |
|         z.parent = y;
 | |
|         if (y == this.nil) {
 | |
|             this.root = z;
 | |
|         } else if (z.key< y.key) {
 | |
|             y.left = z;
 | |
|         } else {
 | |
|             y.right = z;
 | |
|         }
 | |
|         z.left = this.nil;
 | |
|         z.right = this.nil;
 | |
|         z.color = "red";
 | |
|         this.insertFixup(z);
 | |
|         this.size++;
 | |
|     }
 | |
| 
 | |
|     function insertFixup(z) {
 | |
|         while (z.parent.color == "red") {
 | |
|             if (z.parent.parent && z.parent == z.parent.parent.left) {
 | |
|                 local y = z.parent.parent.right;
 | |
|                 if (y.color == "red") {
 | |
|                     z.parent.color = "black";
 | |
|                     y.color = "black";
 | |
|                     z.parent.parent.color = "red";
 | |
|                     z = z.parent.parent;
 | |
|                 } else {
 | |
|                     if (z == z.parent.right) {
 | |
|                         z = z.parent;
 | |
|                         this.leftRotate(z);
 | |
|                     }
 | |
|                     z.parent.color = "black";
 | |
|                     z.parent.parent.color = "red";
 | |
|                     this.rightRotate(z.parent.parent);
 | |
|                 }
 | |
|             } else {
 | |
|                 if (z.parent.parent && z.parent.parent.left.color == "red") {
 | |
|                     z.parent.color = "black";
 | |
|                     z.parent.parent.left.color = "black";
 | |
|                     z.parent.parent.color = "red";
 | |
|                     z = z.parent.parent;
 | |
|                 } else {
 | |
|                     if (z == z.parent.left) {
 | |
|                         z = z.parent;
 | |
|                         this.rightRotate(z);
 | |
|                     }
 | |
|                     z.parent.color = "black";
 | |
|                     if (z.parent.parent) z.parent.parent.color = "red";
 | |
|                     this.leftRotate(z.parent.parent);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         this.root.color = "black";
 | |
|     }
 | |
| 
 | |
|     function leftRotate(x) {
 | |
|         if (!x) return;
 | |
|         local y = x.right;
 | |
|         x.right = y.left;
 | |
|         if (y.left != this.nil) {
 | |
|             y.left.parent = x;
 | |
|         }
 | |
|         y.parent = x.parent;
 | |
|         if (x.parent == this.nil) {
 | |
|             this.root = y;
 | |
|         } else if (x == x.parent.left) {
 | |
|             x.parent.left = y;
 | |
|         } else {
 | |
|             x.parent.right = y;
 | |
|         }
 | |
|         y.left = x;
 | |
|         x.parent = y;
 | |
|     }
 | |
| 
 | |
|     function rightRotate(x) {
 | |
|         local y = x.left;
 | |
|         x.left = y.right;
 | |
|         if (y.right != this.nil) {
 | |
|             y.right.parent = x;
 | |
|         }
 | |
|         y.parent = x.parent;
 | |
|         if (x.parent == this.nil) {
 | |
|             this.root = y;
 | |
|         } else if (x == x.parent.left) {
 | |
|             x.parent.left = y;
 | |
|         } else {
 | |
|             x.parent.right = y;
 | |
|         }
 | |
|         y.right = x;
 | |
|         x.parent = y;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     function minimum(...) {
 | |
|         local node = this.root;
 | |
|         if (vargv.len() > 0) node = vargv[0];
 | |
|         while (node.left != this.nil) {
 | |
|             node = node.left;
 | |
|         }
 | |
|         return node;
 | |
|     }
 | |
| 
 | |
|     function transplant(u, v) {
 | |
|         if (u.parent == this.nil) {
 | |
|             this.root = v;
 | |
|         } else if (u == u.parent.left) {
 | |
|             u.parent.left = v;
 | |
|         } else {
 | |
|             u.parent.right = v;
 | |
|         }
 | |
|         v.parent = u.parent;
 | |
|     }
 | |
| 
 | |
|     function deleteFixup(x) {
 | |
|         while (x != this.root && x.color == "black") {
 | |
|             if (x == x.parent.left) {
 | |
|                 local w = x.parent.right;
 | |
|                 if (w.color == "red") {
 | |
|                     w.color = "black";
 | |
|                     x.parent.color = "red";
 | |
|                     this.leftRotate(x.parent);
 | |
|                     w = x.parent.right;
 | |
|                 }
 | |
|                 if (w.left.color == "black" && w.right.color == "black") {
 | |
|                     w.color = "red";
 | |
|                     x = x.parent;
 | |
|                 } else {
 | |
|                     if (w.right.color == "black") {
 | |
|                         w.left.color = "black";
 | |
|                         w.color = "red";
 | |
|                         this.rightRotate(w);
 | |
|                         w = x.parent.right;
 | |
|                     }
 | |
|                     w.color = x.parent.color;
 | |
|                     x.parent.color = "black";
 | |
|                     w.right.color = "black";
 | |
|                     this.leftRotate(x.parent);
 | |
|                     x = this.root;
 | |
|                 }
 | |
|             } else {
 | |
|                 local w = x.parent.left;
 | |
|                 if (w.color == "red") {
 | |
|                     w.color = "black";
 | |
|                     x.parent.color = "red";
 | |
|                     this.rightRotate(x.parent);
 | |
|                     w = x.parent.left;
 | |
|                 }
 | |
|                 if (w.right.color == "black" && w.left.color == "black") {
 | |
|                     w.color = "red";
 | |
|                     x = x.parent;
 | |
|                 } else {
 | |
|                     if (w.left.color == "black") {
 | |
|                         w.right.color = "black";
 | |
|                         w.color = "red";
 | |
|                         this.leftRotate(w);
 | |
|                         w = x.parent.left;
 | |
|                     }
 | |
|                     w.color = x.parent.color;
 | |
|                     x.parent.color = "black";
 | |
|                     w.left.color = "black";
 | |
|                     this.rightRotate(x.parent);
 | |
|                     x = this.root;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|         x.color = "black";
 | |
|     }
 | |
| 
 | |
|     function deleteNode(z) {
 | |
|         local y = z;
 | |
|         local yOriginalColor = y.color;
 | |
|         local x;
 | |
|         if (z.left == this.nil) {
 | |
|             x = z.right;
 | |
|             this.transplant(z, z.right);
 | |
|         } else if (z.right == this.nil) {
 | |
|             x = z.left;
 | |
|             this.transplant(z, z.left);
 | |
|         } else {
 | |
|             y = this.minimum(z.right);
 | |
|             yOriginalColor = y.color;
 | |
|             x = y.right;
 | |
|             if (y.parent == z) {
 | |
|                 x.parent = y;
 | |
|             } else {
 | |
|                 this.transplant(y, y.right);
 | |
|                 y.right = z.right;
 | |
|                 y.right.parent = y;
 | |
|             }
 | |
|             this.transplant(z, y);
 | |
|             y.left = z.left;
 | |
|             y.left.parent = y;
 | |
|             y.color = z.color;
 | |
|         }
 | |
|         if (yOriginalColor == "black") {
 | |
|             this.deleteFixup(x);
 | |
|         }
 | |
|         this.size--;
 | |
|     }
 | |
| 
 | |
|     function inorderTraversal(...) {
 | |
|         local node = this.root;
 | |
|         if (vargv.len() > 0) node = vargv[0];
 | |
|         if (node == this.nil) {
 | |
|             return;
 | |
|         }
 | |
|         this.inorderTraversal(node.left);
 | |
|         print(node.key + "(" + node.color + ") ");
 | |
|         this.inorderTraversal(node.right);
 | |
|     }
 | |
| 
 | |
|     function getSize() {
 | |
|         return this.size;
 | |
|     }
 | |
| 
 | |
|     function pop() {
 | |
|         if (this.size <= 0) return null;
 | |
|         local z = this.minimum();
 | |
|         if (z != this.nil) {
 | |
|             this.deleteNode(z);
 | |
|             return z;
 | |
|         }
 | |
|         return null;
 | |
|     }
 | |
| 
 | |
|     function GetPop() {
 | |
|         if (this.size <= 0) return null;
 | |
|         local z = this.minimum();
 | |
|         if (z != this.nil) {
 | |
|             return z;
 | |
|         }
 | |
|         return null;
 | |
|     }
 | |
| } |