Exemplo n.º 1
0
        /// <summary>The actual insertion function, recursive version.</summary>
        /// <remarks>
        /// The actual insertion function, recursive version.
        /// PLEASE NOTE that the implementation has been adapted to consume less stack memory
        /// </remarks>
        private char Insert(TernaryTree.TreeInsertionParams @params)
        {
            char?newBranch = InsertNewBranchIfNeeded(@params);

            if (newBranch == null)
            {
                return(InsertIntoExistingBranch(@params));
            }
            else
            {
                return((char)newBranch);
            }
        }
Exemplo n.º 2
0
        // PLEASE NOTE that this function is a result of refactoring "insert" method which
        // is a modification of the original work
        // Returns null if insertion is not needed and the id of the new node if insertion was performed
        private char?InsertNewBranchIfNeeded(TernaryTree.TreeInsertionParams @params)
        {
            char p = @params.p;

            char[] key   = @params.key;
            int    start = @params.start;
            char   val   = @params.val;
            int    len   = Strlen(key, start);

            if (p == 0)
            {
                // this means there is no branch, this node will start a new branch.
                // Instead of doing that, we store the key somewhere else and create
                // only one node with a pointer to the key
                p = freenode++;
                // holds data
                eq[p] = val;
                length++;
                hi[p] = (char)0;
                if (len > 0)
                {
                    // indicates branch is compressed
                    sc[p] = (char)0xFFFF;
                    // use 'lo' to hold pointer to key
                    lo[p] = (char)kv.Alloc(len + 1);
                    Strcpy(kv.GetArray(), lo[p], key, start);
                }
                else
                {
                    sc[p] = (char)0;
                    lo[p] = (char)0;
                }
                return(p);
            }
            else
            {
                return(null);
            }
        }
Exemplo n.º 3
0
        // PLEASE NOTE that this function is a result of refactoring "insert" method which
        // is a modification of the original work
        private char InsertIntoExistingBranch(TernaryTree.TreeInsertionParams @params)
        {
            char initialP = @params.p;

            TernaryTree.TreeInsertionParams paramsToInsertNext = @params;
            while (paramsToInsertNext != null)
            {
                char p = paramsToInsertNext.p;
                // We are inserting into an existing branch hence the id must be non-zero
                System.Diagnostics.Debug.Assert(p != 0);
                char[] key   = paramsToInsertNext.key;
                int    start = paramsToInsertNext.start;
                char   val   = paramsToInsertNext.val;
                int    len   = Strlen(key, start);
                paramsToInsertNext = null;
                if (sc[p] == 0xFFFF)
                {
                    // branch is compressed: need to decompress
                    // this will generate garbage in the external key array
                    // but we can do some garbage collection later
                    char pp = freenode++;
                    // previous pointer to key
                    lo[pp] = lo[p];
                    // previous pointer to data
                    eq[pp] = eq[p];
                    lo[p]  = (char)0;
                    if (len > 0)
                    {
                        sc[p] = kv.Get(lo[pp]);
                        eq[p] = pp;
                        lo[pp]++;
                        if (kv.Get(lo[pp]) == 0)
                        {
                            // key completly decompressed leaving garbage in key array
                            lo[pp] = (char)0;
                            sc[pp] = (char)0;
                            hi[pp] = (char)0;
                        }
                        else
                        {
                            // we only got first char of key, rest is still there
                            sc[pp] = (char)0xFFFF;
                        }
                    }
                    else
                    {
                        // In this case we can save a node by swapping the new node
                        // with the compressed node
                        sc[pp] = (char)0xFFFF;
                        hi[p]  = pp;
                        sc[p]  = (char)0;
                        eq[p]  = val;
                        length++;
                        break;
                    }
                }
                char s = key[start];
                if (s < sc[p])
                {
                    TernaryTree.TreeInsertionParams branchParams = new TernaryTree.TreeInsertionParams(lo[p], key, start, val);
                    char?insertNew = InsertNewBranchIfNeeded(branchParams);
                    if (insertNew == null)
                    {
                        paramsToInsertNext = branchParams;
                    }
                    else
                    {
                        lo[p] = (char)insertNew;
                    }
                }
                else
                {
                    if (s == sc[p])
                    {
                        if (s != 0)
                        {
                            TernaryTree.TreeInsertionParams branchParams = new TernaryTree.TreeInsertionParams(eq[p], key, start + 1,
                                                                                                               val);
                            char?insertNew = InsertNewBranchIfNeeded(branchParams);
                            if (insertNew == null)
                            {
                                paramsToInsertNext = branchParams;
                            }
                            else
                            {
                                eq[p] = (char)insertNew;
                            }
                        }
                        else
                        {
                            // key already in tree, overwrite data
                            eq[p] = val;
                        }
                    }
                    else
                    {
                        TernaryTree.TreeInsertionParams branchParams = new TernaryTree.TreeInsertionParams(hi[p], key, start, val);
                        char?insertNew = InsertNewBranchIfNeeded(branchParams);
                        if (insertNew == null)
                        {
                            paramsToInsertNext = branchParams;
                        }
                        else
                        {
                            hi[p] = (char)insertNew;
                        }
                    }
                }
            }
            return(initialP);
        }