0

我想从“三元搜索树”库(sourceforgehttp://code.google.com/p/ternary-search-tree/)中修改递归函数。默认行为是在三元搜索树中搜索与指定通配符字符串匹配的所有字符串。即如果我搜索“KE*”,在树中拥有“KEY”、“KE1”、“KE2”会找到所有条目。但我需要相反的行为 - 在三元搜索树(包含通配符)中搜索与指定字符串匹配的所有条目。即如果我搜索“KEY”,在树中有“KE*”、“KEY”、“K*”应该会找到所有条目。

树/节点定义如下:

typedef struct TstNode {
    TstNode( char c ) : splitChar(c), left(0), right(0), mid(0){
    }
    char splitChar;
    TstTree left, right;
    union {
        TstTree mid;
        int index;
    };
} tstNode;

以及具有默认行为的函数:

template <class Object>
void TernarySearchTree<Object>::partialMatchSearch(TstTree tree, const char *key)
{
    if (!tree) return;

    // partial match left
    if (*key == '?' || *key == '*' || *key < tree->splitChar)
    {
        partialMatchSearch( tree->left, key );
    }
    // partial match middle
    if (*key == '?' || *key == '*' || *key == tree->splitChar)
    {
        if ( tree->splitChar && *key )
        {
            if ( *key == '*' )
            {
                partialMatchSearch( tree->mid, key );
            }
            else
            {
                partialMatchSearch( tree->mid, key+1 ); // search next pattern char
            }
        }
    }
    if ( ( *key == 0 ||  *key == '*' ) && tree->splitChar == 0 )
    {
        pmVectorPtr->add( tree->index );
    }

    if (*key == '?' || *key == '*' || *key > tree->splitChar)
    {
        partialMatchSearch( tree->right, key );
    }
}

pmVectorPtr 是一个指向 int 向量的指针,函数 get 以根元素和 searchkey 作为参数调用。我已经尝试过适应它,但还无法理解它。我自己的代码:

template <class Object>
void TernarySearchTree<Object>::partialMatchSearchInverted(TstTree tree, const char *key)
{
    if (!tree) return;

    if((tree->splitChar == '*') && ( *key != 0 )){
        partialMatchSearchInverted( tree, key+1 );
    }

    if( *key != 0 ){
        if (*key < tree->splitChar){
            partialMatchSearchInverted( tree->left, key );
        }
        if (*key > tree->splitChar){
            partialMatchSearchInverted( tree->right, key );
        }
    }
    if ((*key == tree->splitChar) || (tree->splitChar == '*')){
        if ( tree->splitChar || *key ){
            partialMatchSearchInverted( tree->mid, key+1 ); // search next pattern char
        }
    }
    if ( ( *key == 0 ) && ( tree->splitChar == 0 ) ){
        pmVectorPtr->add( tree->index );
    }
}

我已经广泛使用调试器对此进行了编码,据我所知,它“似乎”可以工作(即使通配符位于字符串的开头或中间)。但是,如果我在树中添加示例:“K*”和“Ke*”,它只会为“Key”找到一个解决方案(在本例中为 Ke*)。如果我从树中删除“Ke*”,它会为“Key”的搜索查询找到“K*”。我还是不明白为什么。

有什么想法吗?


附录(我的测试用例):

#include <iostream>
#include "ternarySearchTree/ternarySearchTree.h"

int main(int argc, char *argv[]){
    TernarySearchTree<string> tst;
    Vector< TstItem<String> > itemVector;
    {
        TstItem<String> item( "Ke*", "Value" );
        itemVector.add( item );
    }
    {
        TstItem<String> item( "K*", "Value" );
        itemVector.add( item );
    }
    {
        TstItem<String> item( "Ka*", "Value" );
        itemVector.add( item );
    }
    tst.buildBalancedTree(itemVector);

    Vector<int> matches = tst.partialMatchSearchInverted("Key");// will only find Ke* (wrong - it should find Ke* and K*), if I remove Ke* above it would find K* (right), if I remove that also it would find nothing (also right)
    for (unsigned j=0;j<matches.count();j++)
    {
        std::cout<<"Matching: "<< tst.getKey( matches[j] ) <<" -  "<< tst.getValue( matches[j] )->c_str()<<std::endl;
    }
    std::cout<<"total matches "<< matches.count()<<std::endl;
    return 0;
}
4

1 回答 1

0

好的,我终于可以找到我的问题了:我仍然完全不明白三叉树是如何工作的。因此,当通配符可能位于这些分支中的某个位置时,我没有访问左右节点(遗憾的是,几乎每次都如此)。所以我的最终算法比在三叉树中的搜索要慢得多(我担心复杂性可能会像 O(n)),但至少我让它工作了。

所以看起来这个数据结构不适合我的需要(搜索通配符字符串)——我可能会用线性列表获得相同的速度。但是,如果有类似问题的人有一天会发现这个问题,这是我的代码(但我不建议在实际应用程序中使用它,因为它很慢而且我猜周围还有其他结构可以更好地处理这些事情):

template <class Object>
void TernarySearchTree<Object>::partialMatchSearchInverted(TstTree tree, const char *key)
{
    if (!tree) return;
    if((tree->splitChar == '*') && ( *key != 0 )){
        partialMatchSearchInverted( tree, key+1 ); // wildcard occured, search same node with next key
    }
    if( *key != 0 ){
        if (*key < tree->splitChar){
            partialMatchSearchInverted( tree->left, key );
        }else if('*' < tree->splitChar){ // a wildcard could be in this branch
            partialMatchSearchInverted( tree->left, key );
        }
        if (*key > tree->splitChar){
            partialMatchSearchInverted( tree->right, key );
        }else if('*' > tree->splitChar){ // a wildcard could be here too
            partialMatchSearchInverted( tree->right, key );
        }
    }
    if ((*key == tree->splitChar) || (tree->splitChar == '*')){
        if (*key != 0){
            partialMatchSearchInverted( tree->mid, key+1 ); // search next pattern char
        }
    }
    if ( ( *key == 0 ) && ( tree->splitChar == 0 ) ){
        pmVectorPtr->add( tree->index );
    }
}
于 2012-11-29T16:09:14.407 回答