「三分探索木」ライブラリ ( sourceforge & http://code.google.com/p/ternary-search-tree/ )から再帰関数を変更したい。デフォルトの動作では、指定されたワイルドカード文字列に一致するすべての文字列を三分検索ツリーで検索します。つまり、ツリーに 'KEY'、'KE1'、'KE2' があると、'KE*' を検索するとすべてのエントリが見つかります。しかし、逆の動作が必要です。指定された文字列に一致するすべてのエントリを (ワイルドカードを含む) 三分探索ツリーで検索します。つまり、ツリーに 'KE*'、'KEY'、'K*' があると、'KEY' を検索するとすべてのエントリが見つかるはずです。
ツリー/ノードは次のように定義されます。
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 の Vector への Pointer であり、関数 get は root-element と 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*) が 1 つしか見つかりません。ツリーから '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;
}