/// /// This file is part of ILNumerics Community Edition. /// /// ILNumerics Community Edition - high performance computing for applications. /// Copyright (C) 2006 - 2012 Haymo Kutschbach, http://ilnumerics.net /// /// ILNumerics Community Edition is free software: you can redistribute it and/or modify /// it under the terms of the GNU General Public License version 3 as published by /// the Free Software Foundation. /// /// ILNumerics Community Edition is distributed in the hope that it will be useful, /// but WITHOUT ANY WARRANTY; without even the implied warranty of /// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the /// GNU General Public License for more details. /// /// You should have received a copy of the GNU General Public License /// along with ILNumerics Community Edition. See the file License.txt in the root /// of your distribution package. If not, see . /// /// In addition this software uses the following components and/or licenses: /// /// ================================================================================= /// The Open Toolkit Library License /// /// Copyright (c) 2006 - 2009 the Open Toolkit library. /// /// Permission is hereby granted, free of charge, to any person obtaining a copy /// of this software and associated documentation files (the "Software"), to deal /// in the Software without restriction, including without limitation the rights to /// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of /// the Software, and to permit persons to whom the Software is furnished to do /// so, subject to the following conditions: /// /// The above copyright notice and this permission notice shall be included in all /// copies or substantial portions of the Software. /// /// ================================================================================= /// using System; using System.Collections.Generic; using System.Linq; using System.Text; using keytype = System.Int32; namespace ILNumerics.Data { /// /// incomplete BTree implementation (it lags of a remove method) /// /// value element type public class ILBTree { //private static readonly int ORDER = 4; // max number of childs //private static readonly int MAX_KEYS = 3; // uneven ! (order - 1) //private static readonly int MIN_CHILDS = 2; //private static readonly int MIN_KEYS = 1; // uneven ! (order / 2 - 1) private static int m_order = 24; public static int ORDER { get { return m_order; } set { if (value / 2 * 2 != value) { value++; } m_order = value; MAX_KEYS = value -1; MIN_KEYS = value / 2 - 1; } } // max number of childs public static int MAX_KEYS = 15; // uneven ! (order - 1) public static int MIN_KEYS = 7; // uneven ! (order / 2 - 1) public static int DEFAULT_LIST_CAPACITY = 8; private int m_nodeCount = 0; private int m_levelCount = 1; private nodetype m_root; //private class itemtype { // public keytype Key; // public List Values; // //private itemtype () { // // Key = -1; // // Values = new LinkedList(); // //} // public itemtype (keytype key, T value) { // Key = key; // Values = new List(8); // Values.Add(value); // } // public override string ToString() { // return String.Format("K:{0} Count:{1}",Key,Values.Count); // } //} private class nodetype { //public itemtype[] Items; public int[] Keys; public List[] Values; public nodetype[] Childs; /// /// number of keys in the node /// public int Count; public nodetype() { Count = 0; //Items = new itemtype[ MAX_KEYS ]; Keys = new int[MAX_KEYS]; Values = new List[MAX_KEYS]; Childs = new nodetype[ MAX_KEYS + 1 ]; } public override string ToString() { string itemDesc = "---"; if (Count > 0) { itemDesc = String.Format("{0} - {1}",Keys[0],Keys[Count-1]); } return String.Format("{0} Items:[{1}]",Count,itemDesc); } } #region constructor public ILBTree() { m_root = new nodetype(); m_nodeCount = 1; } #endregion #region public interface public int NodeCount { get { return m_nodeCount; } } public int LevelCount { get { return m_levelCount; } } public void Add(keytype key, T value) { if (m_root.Count >= MAX_KEYS) { nodetype newright = new nodetype(); keytype upkey; List upval; SplitNode(m_root,newright, out upkey, out upval); nodetype newRoot = new nodetype(); newRoot.Childs[0] = m_root; newRoot.Childs[1] = newright; newRoot.Keys[0] = upkey; newRoot.Values[0] = upval; newRoot.Count = 1; m_root = newRoot; m_nodeCount += 2; m_levelCount++; } AddValue(key, value, m_root); } #endregion #region private helpers /// /// is the key contained in curNode ? /// /// /// /// /// private unsafe static bool SearchNode(nodetype curNode, keytype key, ref int location) { int loc = 0, max = curNode.Count; int[] curNodeKeys = curNode.Keys; for (; loc < max; loc++) { int curKey = curNodeKeys[loc]; if (curKey == key) { location = loc; return true; } else if (curKey > key) { location = loc; return false; } } location = loc; return false; //int loc = 0, max = curNode.Count; //foreach (keytype curKey in curNode.Keys) { // if (curKey == key) { // location = loc; // return true; // } else if (curKey > key) { // location = loc; // return false; // } // if (++loc >= max) break; //} //location = loc; //return false; //int loc = curNode.Count - 1; //fixed (int* keys = curNode.Keys) { // int* curKey = keys + loc; // do { // if (*curKey == key) { // location = loc; // return true; // } else if (*curKey < key) { // location = ++loc; // return false; // } // curKey--; // } while (loc --> 0); //} //location = 0; //return false; } private void AddValue(keytype key, T value, nodetype curNode) { System.Diagnostics.Debug.Assert(curNode.Count < MAX_KEYS); while (true) { // search node (inlined from func) short max = (short)curNode.Count; short location = 0; int[] curNodeKeys = curNode.Keys; for (; location < max; location++) { int curKey = curNodeKeys[location]; if (curKey == key) { curNode.Values[location].Add(value); return; } if (curKey > key) { break; } } nodetype childNode = curNode.Childs[location]; if (childNode == null) { // insert right here var newVals = new List(8); newVals.Add(value); InsertItemIntoNode(curNode,key,newVals,location,null); break; } else { // check if the child is filled up allready if (childNode.Count >= MAX_KEYS) { nodetype newRightChild = new nodetype(); int upkey; List upval; SplitNode(childNode, newRightChild, out upkey, out upval); m_nodeCount++; InsertItemIntoNode(curNode,upkey, upval, location, newRightChild); // cur node should always have space left! // in which subtree to go? if (key == upkey) { curNode.Values[location].Add(value); return; } if (key > upkey) location++; } //AddValue(key, value, curNode.Childs[location]); curNode = curNode.Childs[location]; } } } //private void AddValue(keytype key, T value, nodetype curNode) { // System.Diagnostics.Debug.Assert(curNode.Count < MAX_KEYS); // int location; // if (SearchNode(curNode, key, out location)) { // curNode.Values[location].Add(value); // } else { // nodetype childNode = curNode.Childs[location]; // if (childNode == null) { // // insert right here // var newVals = new List(8); // newVals.Add(value); // InsertItemIntoNode(curNode,key,newVals,location,null); // } else { // // check if the child is filled up allready // if (childNode.Count >= MAX_KEYS) { // nodetype newRightChild = new nodetype(); // int upkey; // List upval; // SplitNode(childNode, newRightChild, out upkey, out upval); // m_nodeCount++; // InsertItemIntoNode(curNode,upkey, upval, location, newRightChild); // cur node should always have space left! // // in which subtree to go? // if (key == upkey) { // curNode.Values[location].Add(value); // return; // } // if (key > upkey) // location++; // } // AddValue(key, value, curNode.Childs[location]); // } // } //} #region break #endregion //private void AddValue(keytype key, T value, nodetype curNode, ref itemtype upcomingItem, ref nodetype rightchild) { // if (curNode == null) { // // we came from a leaf! let the parent handle the insertion // upcomingItem = new itemtype(key,value); // rightchild = null; // return; // } // System.Diagnostics.Debug.Assert(curNode.Count < MAX_KEYS); // int location; // if (SearchNode(curNode, key, out location)) { // curNode.Items[location].Values.AddFirst(value); // upcomingItem = null; // } else { // nodetype childNode = curNode.Childs[location]; // if (childNode.Count >= MAX_KEYS) { // nodetype newRightChild = new nodetype(); // itemtype newUpItem; // SplitNode(childNode, newRightChild, out newUpItem); // InsertItemIntoNode(curNode,newUpItem,location,newRightChild); // cur node should always have space left! // // in which subtree to go? // if (key > newUpItem.Key) // location++; // if (key == newUpItem.Key) { // curNode.Items[location].Values.AddFirst(value); // upcomingItem = null; // return; // } // } // // location = index of child/ insertion point // AddValue(key, value, curNode.Childs[location], ref upcomingItem, ref rightchild); // // handle upcoming node // if (upcomingItem != null) { // if (curNode.Count < MAX_KEYS) { // // insert right here // InsertItemIntoNode(curNode, upcomingItem, location, rightchild); // upcomingItem = null; // } else { // // split the node and move median up // SplitNode(curNode, upcomingItem, location, ref upcomingItem, ref rightchild); // } // } // } //} private void SplitNode(nodetype curNode, nodetype newRight, out keytype upKey, out List upval) { System.Diagnostics.Debug.Assert(Math.Round(curNode.Count / 2.0) != curNode.Count / 2.0); System.Diagnostics.Debug.Assert(curNode.Count == (MIN_KEYS * 2 + 1)); System.Diagnostics.Debug.Assert(curNode.Count == MAX_KEYS); System.Diagnostics.Debug.Assert(newRight != null && newRight.Childs != null && newRight.Keys != null); System.Diagnostics.Debug.Assert(newRight.Childs.Length == ORDER && newRight.Keys.Length == MAX_KEYS && newRight.Values.Length == MAX_KEYS); for (int i = MIN_KEYS + 1, ni = 0; ni < MIN_KEYS; ni++, i++) { newRight.Keys[ni] = curNode.Keys[i]; newRight.Values[ni] = curNode.Values[i]; newRight.Childs[ni+1] = curNode.Childs[i+1]; // clear old data curNode.Keys[i] = -1; curNode.Values[i] = null; curNode.Childs[i+1] = null; } curNode.Count = MIN_KEYS; newRight.Count = MIN_KEYS; newRight.Childs[0] = curNode.Childs[MIN_KEYS + 1]; upKey = curNode.Keys[MIN_KEYS]; upval = curNode.Values[MIN_KEYS]; // clear old data curNode.Keys[MIN_KEYS] = -1; curNode.Values[MIN_KEYS] = null; curNode.Childs[MIN_KEYS + 1] = null; } //private void SplitNode(nodetype curNode, itemtype newItem, int location, ref itemtype upcomingItem, ref nodetype upcomingrightnode) { // var newnode = new nodetype(); // if (location <= MIN_KEYS) { // // copy right node // for (int ci = MIN_KEYS, ni = 0; ci < MAX_KEYS; ci++, ni++ ) { // newnode.Items[ni] = curNode.Items[ci]; // newnode.Childs[ni+1] = curNode.Childs[ci]; // } // // copy curNode // for (int ci = MIN_KEYS; ci --> location; ) { // curNode.Items[ci+1] = curNode.Items[ci]; // curNode.Childs[ci+1] = curNode.Childs[ci]; // } // curNode.Count = MIN_KEYS + 1; // newnode.Count = MAX_KEYS - MIN_KEYS; // // insert new item // curNode.Items[location] = newItem; // curNode.Childs[location] = upcomingrightnode; // newnode.Childs[0] = curNode.Childs[MIN_KEYS]; // // give the median back upwards // upcomingItem = curNode.Items[MIN_KEYS]; // upcomingrightnode = newnode; // } else { // // copy right node -> up to insert location // int i = MIN_KEYS, ni = 0; // for (; i < location; i++, ni++) { // newnode.Items[ni] = curNode.Items[i]; // newnode.Childs[ni+1] = curNode.Childs[i]; // } // // insert new item // newnode.Items[ni] = newItem; // newnode.Childs[ni++] = upcomingrightnode; // // copy rest of node to right side // for (; i < curNode.Count; i++, ni++) { // newnode.Items[ni] = curNode.Items[i]; // newnode.Childs[ni+1] = curNode.Childs[i]; // } // // update curNode // curNode.Count = MIN_KEYS + 1; // newnode.Count = ni; // newnode.Childs[0] = curNode.Childs[MIN_KEYS + 1]; // upcomingItem = curNode.Items[MIN_KEYS + 1]; // upcomingrightnode = newnode; // } // m_nodeCount++; //} private void InsertItemIntoNode(nodetype curNode, keytype newKey,List newvalue, int location, nodetype rigthchild) { int a = curNode.Count; for (; a --> location; ) { curNode.Keys[a+1] = curNode.Keys[a]; curNode.Values[a+1] = curNode.Values[a]; curNode.Childs[a+2] = curNode.Childs[a+1]; } // insert a new linked list at freed position curNode.Keys[location] = newKey; curNode.Values[location] = newvalue; curNode.Childs[location+1] = rigthchild; curNode.Count++; } #endregion } }