/// <summary> /// Next node /// </summary> /// <returns></returns> public bool Next() { switch (_action) { case Action.Right: _current = _right; while (_current.LEFT != 0) { _current = read_node(_current.LEFT); } _action = _current.RIGHT != 0 ? Action.Right : Action.Parent; if (_action == Action.Right) { _right = read_node(_current.RIGHT); } return(true); case Action.Parent: while (_current.PARENT != 0) { VSAvlNode previous = _current; _current = read_node(_current.PARENT); if (_current.LEFT == previous.ID) { _action = _current.RIGHT != 0 ? Action.Right : Action.Parent; if (_action == Action.Right) { _right = read_node(_current.RIGHT); } return(true); } } _action = Action.End; return(false); case Action.Current: _action = _current.RIGHT != 0 ? Action.Right : Action.Parent; if (_current.RIGHT > 0) { _right = read_node(_current.RIGHT); } return(true); default: return(false); } }
/// <summary> /// Read node /// </summary> /// <param name="id"></param> /// <returns></returns> public VSAvlNode read_node(long id) { VSAvlNode av = new VSAvlNode(this); av.Read(id); return(av); }
/// <summary> /// Balance after deletion /// </summary> /// <param name="node"></param> /// <param name="balance"></param> private void balance_delete(VSAvlNode bnode, int bal) { int balance = bal; VSAvlNode node = bnode; bool ret = false; while ((node != null) & (!ret)) { balance = (node.BALANCE += balance); if (balance == -2) { VSAvlNode left = read_node(node.LEFT); if (left.BALANCE <= 0) { node = rotate_right(node); if (node.BALANCE == 1) { ret = true; } } else { node = rotate_left_right(node); } } else if (balance == 2) { VSAvlNode right = read_node(node.RIGHT); if (right.BALANCE >= 0) { node = rotate_left(node); if (node.BALANCE == -1) { ret = true; } } else { node = rotate_right_left(node); } } else if (balance != 0) { ret = true; } VSAvlNode parent = null; if (node.PARENT > 0) { parent = read_node(node.PARENT); balance = (parent.LEFT == node.ID) ? 1 : -1; } node = parent; } }
/// <summary> /// Balance tree after insertion /// </summary> /// <param name="b_node"></param> /// <param name="balance"></param> private void balance_insert(VSAvlNode bnode, int bal) { VSAvlNode node = bnode; bool ret = false; int balance = bal; while ((node != null) & (!ret)) { balance = (node.BALANCE += balance); if (balance == 0) { ret = true; } else { if (balance == -2) { VSAvlNode left = read_node(node.LEFT); if (left.BALANCE == -1) { rotate_right(node); } else { rotate_left_right(node); } ret = true; } else if (balance == 2) { VSAvlNode right = read_node(node.RIGHT); if (right.BALANCE == 1) { rotate_left(node); } else { rotate_right_left(node); } ret = true; } VSAvlNode parent = null; if (node.PARENT > 0) { parent = read_node(node.PARENT); balance = parent.LEFT == node.ID ? -1 : 1; } node = parent; } } }
/// <summary> /// Get ID by full or partial string key (first if if non-unique index) /// </summary> /// <param name="k"></param> /// <returns></returns> public long Find(byte[] key, bool partial = false) { long id = search_node(key, partial); if (id < 0) { return(-1); } VSAvlNode a = read_node(id); return(a.REF); }
/// <summary> /// Get all IDs by full byte key (single ID if unique index) /// </summary> /// <param name="k"></param> /// <returns></returns> public long[] FindAll(byte[] key, bool partial = false) { if (partial) { //string k = VSLib.ConvertByteToString(key); List <long> l = new List <long>(); reset(key, true); while (Next()) { bool eq = true; byte[] b = CurrentKeyBytes; for (int i = 0; i < key.Length; i++) { if (key[i] != b[i]) { eq = false; break; } } if (!eq) { break; } int j = CurrentRefs.Length; for (int i = 0; i < j; i++) { l.Add(this.CurrentRefs[i]); } } return(l.ToArray()); } else { long id = search_node(key, false); if (id < 0) { return(new long[0]); } VSAvlNode a = read_node(id); return(a.REFS); } }
/// <summary> /// Reset /// </summary> public void Reset() { _current = new VSAvlNode(this); if (ROOT > 0) { _right = _current = read_node(ROOT); _action = Action.Right; } else { _action = Action.End; } }
/// <summary> /// Rotate Left /// </summary> /// <param name="node"></param> /// <returns></returns> private VSAvlNode rotate_left(VSAvlNode node) { VSAvlNode right = read_node(node.RIGHT); long ParentID = node.PARENT; long RightLeftID = right.LEFT; right.PARENT = node.PARENT; right.LEFT = node.ID; node.RIGHT = RightLeftID; node.PARENT = right.ID; if (RightLeftID > 0) { VSAvlNode rightLeft = read_node(RightLeftID); rightLeft.PARENT = node.ID; } if (node.ID == ROOT) //Root? { ROOT = right.ID; } else { VSAvlNode parent = read_node(ParentID); if (parent.RIGHT == node.ID) { parent.RIGHT = right.ID; } else if (parent.LEFT == node.ID) { parent.LEFT = right.ID; } } right.BALANCE--; node.BALANCE = -right.BALANCE; return(right); }
/// <summary> /// Search node by key /// </summary> /// <param name="key"></param> /// <returns>-1 - not found</returns> private long search_node(byte[] key, bool partial = false) { long ret_node = -1; long nodeID = ROOT; while (nodeID > 0) { VSAvlNode node = read_node(nodeID); int compare = compare_keys(key, node.KEY, partial); // __compares++; if (compare < 0) { if (partial) { if (ret_node >= 0) { break; } } nodeID = node.LEFT; } else if (compare > 0) { nodeID = node.RIGHT; } else { ret_node = node.ID; if (!partial) { break; } else { nodeID = node.LEFT; } } } return(ret_node); }
/// <summary> /// Rotate node right /// </summary> /// <param name="node"></param> /// <returns></returns> private VSAvlNode rotate_right(VSAvlNode node) { VSAvlNode left = read_node(node.LEFT); long LeftRightID = left.RIGHT; long ParentID = node.PARENT; left.PARENT = ParentID; left.RIGHT = node.ID; node.LEFT = LeftRightID; node.PARENT = left.ID; if (LeftRightID > 0) { VSAvlNode leftRight = read_node(LeftRightID); leftRight.PARENT = node.ID; } if (node.ID == ROOT) //Root? { ROOT = left.ID; } else { VSAvlNode parent = read_node(ParentID); if (parent.LEFT == node.ID) { parent.LEFT = left.ID; } else if (parent.RIGHT == node.ID) { parent.RIGHT = left.ID; } } left.BALANCE++; node.BALANCE = -left.BALANCE; return(left); }
/// <summary> /// Create new AVLNODE - private method /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <param name="parent"></param> /// <returns></returns> private VSAvlNode create_node(byte[] key, long value, long parent) { VSAvlNode a = new VSAvlNode(this); if (POOL == 0) { POOL = sp.GetFreePoolNumber(); } if (POOL < 0) { throw new VSException(DEFS.E0013_SPACE_NOT_AVAILABLE_CODE, "- no free pools for dynamic allocation"); } a.Create(key, value, parent, POOL); if (ROOT == 0) { ROOT = a.ID; } return(a); }
/// <summary> /// Replace Node, used by "DeleteNode" /// </summary> /// <param name="node_id"></param> /// <param name="replacement_id"></param> private void replace_node(VSAvlNode target, VSAvlNode repl) { repl.PARENT = target.PARENT; if (target.ID == ROOT) { ROOT = repl.ID; } else { VSAvlNode parent = read_node(target.PARENT); if (parent.LEFT == target.ID) { parent.LEFT = repl.ID; } else { parent.RIGHT = repl.ID; } balance_delete(repl, 0); } }
/// <summary> /// Reset by key /// </summary> /// <param name="key"></param> private void reset(byte[] key, bool partial = false) { _current = new VSAvlNode(this); if (ROOT > 0) { long id = search_node(key, partial); if (id > 0) { _action = Action.Current; _right = read_node(id); _current = _right; } else { _action = Action.End; } } else { _action = Action.End; } }
/// <summary> /// Rotate Right Left /// </summary> /// <param name="node"></param> /// <returns></returns> private VSAvlNode rotate_right_left(VSAvlNode node) { VSAvlNode right = read_node(node.RIGHT); VSAvlNode rightLeft = read_node(right.LEFT); long parentID = node.PARENT; long rightLeftLeftID = rightLeft.LEFT; long rightLeftRightID = rightLeft.RIGHT; rightLeft.PARENT = parentID; node.RIGHT = rightLeftLeftID; right.LEFT = rightLeftRightID; rightLeft.RIGHT = right.ID; rightLeft.LEFT = node.ID; right.PARENT = node.PARENT = rightLeft.ID; if (rightLeftLeftID > 0) { VSAvlNode rightLeftLeft = read_node(rightLeftLeftID); rightLeftLeft.PARENT = node.ID; } if (rightLeftRightID > 0) { VSAvlNode rightLeftRight = read_node(rightLeftRightID); rightLeftRight.PARENT = right.ID; } if (node.ID == ROOT) //Root? { ROOT = rightLeft.ID; } else { VSAvlNode parent = read_node(parentID); if (parent.RIGHT == node.ID) { parent.RIGHT = rightLeft.ID; } else { parent.LEFT = rightLeft.ID; } } if (rightLeft.BALANCE == -1) { node.BALANCE = 0; right.BALANCE = 1; } else if (rightLeft.BALANCE == 0) { node.BALANCE = 0; right.BALANCE = 0; } else { node.BALANCE = -1; right.BALANCE = 0; } rightLeft.BALANCE = 0; return(rightLeft); }
/// <summary> /// Add new index (bytes) /// </summary> /// <param name="key"></param> /// <param name="value"></param> /// <returns></returns> public long insert_node(byte[] key, long value) { long rc = -1; _current = null; VSAvlNode node = null; if (ROOT == 0) { ROOT = create_node(key, value, 0).ID; return(ROOT); } else { long nodeID = ROOT; while (nodeID > 0) { node = read_node(nodeID); int compare = compare_keys(key, node.KEY); if (compare < 0) { if (node.LEFT == 0) { node.LEFT = create_node(key, value, node.ID).ID; balance_insert(node, -1); return(node.LEFT); } else { nodeID = node.LEFT; } } else if (compare > 0) { if (node.RIGHT == 0) { node.RIGHT = create_node(key, value, node.ID).ID; balance_insert(node, 1); return(node.RIGHT); } else { nodeID = node.RIGHT; } } else { // Index value already exists if (node.UNIQUE) { this.Error = "Index value already exists"; break; } else { if (node.add_ref(value)) // Add reference for non-unique value { rc = node.ID; } break; } } } } return(rc); }
/// <summary> /// Delete index by AvlNode Id and Object Id /// </summary> /// <param name="key"></param> /// <param name="obj_id">For non-unique index. 0 - delete all </param> /// <returns></returns> internal bool delete_avl_node(long avlnode_id, long obj_id) { VSAvlNode node = read_node(avlnode_id); if ((node.REF_COUNT > 1) & (obj_id > 0)) { return(node.delete_ref(obj_id)); } if (obj_id > 0) { if (obj_id != node.REF) { Error = "ID " + obj_id.ToString() + " is not found for index node ID " + avlnode_id.ToString(); return(false); } } VSAvlNode left; VSAvlNode right; if (node.LEFT == 0) { if (node.RIGHT == 0) { if (node.ID == ROOT) { ROOT = 0; POOL = 0; } else { VSAvlNode parent = read_node(node.PARENT); if (parent.LEFT == node.ID) { parent.LEFT = 0; balance_delete(parent, 1); } else { parent.RIGHT = 0; balance_delete(parent, -1); } } } else { replace_node(node, read_node(node.RIGHT)); } } else if (node.RIGHT == 0) { replace_node(node, read_node(node.LEFT)); } else { VSAvlNode successor = read_node(node.RIGHT); if (successor.LEFT == 0) { successor.PARENT = node.PARENT; successor.LEFT = node.LEFT; successor.BALANCE = node.BALANCE; if (node.LEFT > 0) { left = read_node(node.LEFT); left.PARENT = successor.ID; } if (node.ID == ROOT) //Is it root? { ROOT = successor.ID; } else { VSAvlNode parent = read_node(node.PARENT); if (parent.LEFT == node.ID) { parent.LEFT = successor.ID; } else { parent.RIGHT = successor.ID; } } balance_delete(successor, -1); } else { while (successor.LEFT > 0) { successor = read_node(successor.LEFT); } VSAvlNode successorRight; VSAvlNode successorParent = read_node(successor.PARENT); if (successorParent.LEFT == successor.ID) { successorParent.LEFT = successor.RIGHT; } else { successorParent.RIGHT = successor.RIGHT; } if (successor.RIGHT > 0) { successorRight = read_node(successor.RIGHT); successorRight.PARENT = successorParent.ID; } successor.PARENT = node.PARENT; successor.LEFT = node.LEFT; successor.RIGHT = node.RIGHT; successor.BALANCE = node.BALANCE; right = read_node(node.RIGHT); right.PARENT = successor.ID; if (node.LEFT > 0) { left = read_node(node.LEFT); left.PARENT = successor.ID; } if (node.ID == ROOT) //Root? { ROOT = successor.ID; } else { VSAvlNode parent = read_node(node.PARENT); if (parent.LEFT == node.ID) { parent.LEFT = successor.ID; } else { parent.RIGHT = successor.ID; } } balance_delete(successorParent, 1); } } _current = null; node.Delete(); return(true); }
/// <summary> /// Rotate Left Right /// </summary> /// <param name="node"></param> /// <returns></returns> private VSAvlNode rotate_left_right(VSAvlNode node) { VSAvlNode left = read_node(node.LEFT); VSAvlNode leftRight = read_node(left.RIGHT); long parentID = node.PARENT; long leftRightRightID = leftRight.RIGHT; long leftRightLeftID = leftRight.LEFT; leftRight.PARENT = node.PARENT; node.LEFT = leftRightRightID; left.RIGHT = leftRightLeftID; leftRight.LEFT = left.ID; leftRight.RIGHT = node.ID; left.PARENT = leftRight.ID; node.PARENT = leftRight.ID; if (leftRightRightID > 0) { VSAvlNode leftRightRight = read_node(leftRightRightID); leftRightRight.PARENT = node.ID; } if (leftRightLeftID > 0) { VSAvlNode leftRightLeft = read_node(leftRightLeftID); leftRightLeft.PARENT = left.ID; } if (node.ID == ROOT) //Root? { ROOT = leftRight.ID; } else { VSAvlNode parent = read_node(parentID); if (parent.LEFT == node.ID) { parent.LEFT = leftRight.ID; } else { parent.RIGHT = leftRight.ID; } } if (leftRight.BALANCE == 1) { node.BALANCE = 0; left.BALANCE = -1; } else if (leftRight.BALANCE == 0) { node.BALANCE = 0; left.BALANCE = 0; } else { node.BALANCE = 1; left.BALANCE = 0; } leftRight.BALANCE = 0; return(leftRight); }