【问题标题】:Searching for (NOT with) wildcards inside an ternary search tree在三元搜索树中搜索(不使用)通配符
【发布时间】:2012-11-28 13:55:11
【问题描述】:

我想修改“三元搜索树”库 (sourceforge & http://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;
}

【问题讨论】:

  • 看起来像是对那个 hack 的作者的一个问题(三元搜索树,显然是用 c 编码的,带有一些 c++ 特性)。
  • 谢谢,好点!我也会尝试联系作者,但我不希望联系到他,因为从 2007 年开始,googlecode wiki 页面上仍有未解决的问题。

标签: c++ recursion ternary-tree ternary-search-tree


【解决方案1】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-16
    • 2014-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多