示例#1
0
nSearchTreeNode BasicSearchTree::SplitBranch(nSearchTreeNode n,size_t depth)
{
    if (!n || !m_Nodes[n] || m_Nodes[n]->GetDepth()==depth)
        return n;
    // for !n it returns the rootnode
    // for !m_Nodes[n], it fails by returning n.
    // for m_Nodes[n]->GetDepth()==depth, it's a special case (given position is a node)
    // so we just return n.

    SearchTreeNode* child = m_Nodes[n];

    nSearchTreeNode old_parent = child->GetParent();

    // Create new node "middle", add it to old_parent in place of child.

    // Calculate the parent offset and the new labels' parameters.
    size_t parent_offset = depth - child->GetLabelStartDepth();
    nSearchTreeLabel labelno = child->GetLabelNo();

    unsigned int oldlabelstart = child->GetLabelStart();
    unsigned int oldlabellen = child->GetLabelLen();

    unsigned int middle_start = oldlabelstart;
    unsigned int middle_len = parent_offset;

    unsigned int child_start = middle_start + middle_len;
    unsigned int child_len = oldlabellen - middle_len;

    wxChar middle_char = m_Labels[labelno][middle_start];
    wxChar child_char = m_Labels[labelno][child_start];

    // Now we're ready to create the middle node and update accordingly

    SearchTreeNode* newnode = CreateNode(depth,old_parent,labelno,middle_start,middle_len);
    m_Nodes.push_back(newnode);
    nSearchTreeNode middle = m_Nodes.size() - 1;

    // Add child to middle
    child->SetParent(middle);
    child->SetLabel(labelno,child_start,child_len);
    child->RecalcDepth(this);
    newnode->m_Children[child_char]=n;
    child->UpdateItems(this);

    // Add middle to old_parent
    m_Nodes[old_parent]->m_Children[middle_char]=middle;

    return middle;
}
示例#2
0
size_t BasicSearchTree::FindMatches(const wxString& s, std::set<size_t>& result, bool caseSensitive, bool is_prefix)
{
    // NOTE: Current algorithm is suboptimal, but certainly it's much better
    // than an exhaustive search.
    result.clear();
    wxString s2,curcmp,s3;
    SearchTreeNode* curnode = 0;
    BasicSearchTreeIterator it(this);
    SearchTreeItemsMap::iterator it2;

    bool matches;

    if (!caseSensitive)
        s2 = s.Lower();
    else
        s2 = s;

    while (!it.Eof())
    {
        matches = false;
        curnode = m_Nodes[*it];
        if (!curnode)
            break; // Error! Found a NULL Node
        if (curnode->m_Depth < s.length())
        {   // Node's string is shorter than S, therefore it CANNOT be a suffix
            // However, we can test if it does NOT match the current string.
            if (!curnode->m_Depth)
                matches = true;
            else
            {
                s3 = s2.substr(curnode->GetLabelStartDepth(),curnode->GetLabelLen());
                curcmp = curnode->GetLabel(this);
                if (!caseSensitive)
                    curcmp = curcmp.Lower();
                matches = (s3 == curcmp);
            }
        }
        else
        {
            if (curnode->GetLabelStartDepth() >= s2.length())
                matches = is_prefix;
            else
            {
                s3 = s2.substr(curnode->GetLabelStartDepth());
                curcmp = curnode->GetLabel(this);
                if (!caseSensitive)
                    curcmp = curcmp.Lower();
                matches = curcmp.StartsWith(s3);
            }

            if (matches)
            {
                // Begin items addition
                if (!is_prefix)
                {
                    // Easy part: Only one length to search
                    it2 = curnode->m_Items.find(s2.length());
                    if (it2 != curnode->m_Items.end())
                        result.insert(it2->second);
                }
                else
                {
                    for (it2 = curnode->m_Items.lower_bound(s2.length()); it2 != curnode->m_Items.end(); ++it2)
                    {
                        result.insert(it2->second);
                    }
                }
                matches = is_prefix;
                // End items addition
            }
        }
        it.FindNext(matches);
    }
    return result.size();
}
示例#3
0
SearchTreePoint BasicSearchTree::AddNode(const wxString& s, nSearchTreeNode nparent)
{
    SearchTreePoint result(0,0);
    nSearchTreeNode n = 0;
    bool found = this->FindNode(s,nparent,&result);
    if (!found)
    {
        // Create new node

        // If necessary, split the edge with a new node 'middle'
        // If result is exactly a node, middle will be just result.n.
        nSearchTreeNode middle = SplitBranch(result.n,result.depth);

        // Now add the node to the middle node
        SearchTreeNode* newnode;
        wxString newlabel;
        if (m_Nodes[middle]->IsLeaf())
        {
            // If it's a leaf node, just extend the label and change
            // the new node's depth to reflect the changes.
            n = middle;
            newnode = m_Nodes[n];

            // We take the part of the string that corresponds to node middle.
            // Since s starts at nparent's depth, we just get the difference and
            // it will be the position inside the string.
            newlabel = s.substr(m_Nodes[middle]->GetLabelStartDepth() - m_Nodes[nparent]->GetDepth());

            // Modify the leaf node's label to extend the point
            // Since it's a leaf node, we just concatenate to the current label the missing part.
            unsigned int oldlen = newnode->GetDepth() - newnode->GetLabelStartDepth();
            if (oldlen < newlabel.length()) // Safety check against segfaults
            {
                m_Labels[newnode->GetLabelNo()] << newlabel.substr(oldlen);
                m_Labels[newnode->GetLabelNo()].Shrink();
            }
            newnode->SetLabel(newnode->GetLabelNo(),newnode->GetLabelStart(),newlabel.length());
            newnode->RecalcDepth(this);
        }
        else
        {
            // Get the string's depth. This will be the depth of our new leaf node.
            size_t newdepth = m_Nodes[nparent]->GetDepth() + s.length();

            // start = middle's depth - nparent's depth.
            newlabel = s.substr(m_Nodes[middle]->GetDepth() - m_Nodes[nparent]->GetDepth());

            // Now we create the new label to be accessed by the leaf node "newnode".
            m_Labels.push_back(newlabel);
            nSearchTreeLabel nlabel = m_Labels.size() - 1;
            m_Labels[nlabel].Shrink();

            // Finally, we create the new node and link it to "middle".
            newnode = CreateNode(newdepth,middle,nlabel,0,newlabel.length());
            m_Nodes.push_back(newnode);
            n = m_Nodes.size()-1;
            m_Nodes[middle]->m_Children[newlabel[0u]]=n;
        }
        result.n = n;
        result.depth = newnode->GetDepth();

    }
    return result;
}