Beispiel #1
0
        private void Compact(CharVector kx, TernaryTree map, char p)
        {
            int k;

            if (p == 0)
            {
                return;
            }
            if (m_sc[p] == 0xFFFF)
            {
                k = map.Find(m_kv.Array, m_lo[p]);
                if (k < 0)
                {
                    k = kx.Alloc(StrLen(m_kv.Array, m_lo[p]) + 1);
                    StrCpy(kx.Array, k, m_kv.Array, m_lo[p]);
                    map.Insert(kx.Array, k, (char)k);
                }
                m_lo[p] = (char)k;
            }
            else
            {
                Compact(kx, map, m_lo[p]);
                if (m_sc[p] != 0)
                {
                    Compact(kx, map, m_eq[p]);
                }
                Compact(kx, map, m_hi[p]);
            }
        }
Beispiel #2
0
        /// <summary>
        /// Each node stores a character (splitchar) which is part of some key(s). In a
        /// compressed branch (one that only contain a single string key) the trailer
        /// of the key which is not already in nodes is stored externally in the kv
        /// array. As items are inserted, key substrings decrease. Some substrings may
        /// completely disappear when the whole branch is totally decompressed. The
        /// tree is traversed to find the key substrings actually used. In addition,
        /// duplicate substrings are removed using a map (implemented with a
        /// TernaryTree!).
        ///
        /// </summary>
        public virtual void TrimToSize()
        {
            // first balance the tree for best performance
            Balance();

            // redimension the node arrays
            RedimNodeArrays(m_freenode);

            // ok, compact kv array
            CharVector kx = new CharVector();

            kx.Alloc(1);
            TernaryTree map = new TernaryTree();

            Compact(kx, map, m_root);
            m_kv = kx;
            m_kv.TrimToSize();
        }
Beispiel #3
0
        /// <summary>
        /// The actual insertion function, recursive version.
        /// </summary>
        private char Insert(char p, char[] key, int start, char 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       = m_freenode++;
                m_eq[p] = val; // holds data
                m_length++;
                m_hi[p] = (char)0;
                if (len > 0)
                {
                    m_sc[p] = (char)0xFFFF;              // indicates branch is compressed
                    m_lo[p] = (char)m_kv.Alloc(len + 1); // use 'lo' to hold pointer to key
                    StrCpy(m_kv.Array, m_lo[p], key, start);
                }
                else
                {
                    m_sc[p] = (char)0;
                    m_lo[p] = (char)0;
                }
                return(p);
            }

            if (m_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 = m_freenode++;
                m_lo[pp] = m_lo[p]; // previous pointer to key
                m_eq[pp] = m_eq[p]; // previous pointer to data
                m_lo[p]  = (char)0;
                if (len > 0)
                {
                    m_sc[p] = m_kv[m_lo[pp]];
                    m_eq[p] = pp;
                    m_lo[pp]++;
                    if (m_kv[m_lo[pp]] == 0)
                    {
                        // key completly decompressed leaving garbage in key array
                        m_lo[pp] = (char)0;
                        m_sc[pp] = (char)0;
                        m_hi[pp] = (char)0;
                    }
                    else
                    {
                        // we only got first char of key, rest is still there
                        m_sc[pp] = (char)0xFFFF;
                    }
                }
                else
                {
                    // In this case we can save a node by swapping the new node
                    // with the compressed node
                    m_sc[pp] = (char)0xFFFF;
                    m_hi[p]  = pp;
                    m_sc[p]  = (char)0;
                    m_eq[p]  = val;
                    m_length++;
                    return(p);
                }
            }
            char s = key[start];

            if (s < m_sc[p])
            {
                m_lo[p] = Insert(m_lo[p], key, start, val);
            }
            else if (s == m_sc[p])
            {
                if (s != 0)
                {
                    m_eq[p] = Insert(m_eq[p], key, start + 1, val);
                }
                else
                {
                    // key already in tree, overwrite data
                    m_eq[p] = val;
                }
            }
            else
            {
                m_hi[p] = Insert(m_hi[p], key, start, val);
            }
            return(p);
        }