"不完整类型"当打开散列c ++时

时间:2014-11-29 20:25:10

标签: c++11 recursion hash hashtable backtracking

我是C ++的新手,我收到了一个我以前从未见过的错误。我试图通过使用哈希表(开放哈希)的回溯算法进行搜索。

在我进行递归调用之前,我正在搜索哈希表以查看当前位置是否已经被搜索过(并且已经失败),然后插入int的向量" B"当递归调用返回false时进入哈希表,以便可以避免将来搜索相同的位置。

继承我的程序调用文件哈希的函数:

bool open_hash_solve (vector<int> B, vector<Move> & MS, vector<Move> & TMS, OpenHashTable<vector<int>> & H) {

  if (solved(B))
    return true;

  vector<Move> curr = currentMoves(B, TMS);

  for (int m = 0; m < curr.size(); m++) {

    vector<int> moveMade = makeMove(B, curr[m]);

    if (!H.contains(moveMade)){

      if (open_hash_solve(moveMade, MS, TMS, H)){

        MS.insert(MS.begin(), curr[m]);
        return true;
      }
      else
        H.insert(moveMade);
    }
  }
  return false;
}

标题文件与教科书分开链接:

#ifndef SEPARATE_CHAINING_H
#define SEPARATE_CHAINING_H

#include <vector>
#include <list>
#include <string>
#include <algorithm>
#include <functional>
using namespace std;


int nextPrime( int n );

// SeparateChaining Hash table class
//
// CONSTRUCTION: an approximate initial size or default of 101
//
// ******************PUBLIC OPERATIONS*********************
// bool insert( x )       --> Insert x
// bool remove( x )       --> Remove x
// bool contains( x )     --> Return true if x is present
// void makeEmpty( )      --> Remove all items

template <typename HashedObj>
class OpenHashTable
{
 public:
  explicit OpenHashTable( int size = 101 ) : currentSize{ 0 }
  { theLists.resize( 101 ); }

  bool contains( const HashedObj & x ) const
  {
    auto & whichList = theLists[ myhash( x ) ];
    return find( begin( whichList ), end( whichList ), x ) != end( whichList );
  }

  void makeEmpty( )
  {
    for( auto & thisList : theLists )
      thisList.clear( );
  }

  bool insert( const HashedObj & x )
  {
    auto & whichList = theLists[ myhash( x ) ];
    if( find( begin( whichList ), end( whichList ), x ) != end( whichList) )
      return false;
    whichList.push_back( x );

    // Rehash; see Section 5.5
    if( ++currentSize > theLists.size( ) )
      rehash( );

    return true;
  } 

  bool insert( HashedObj && x )
  {
    auto & whichList = theLists[ myhash( x ) ];
    if( find( begin( whichList ), end( whichList ), x ) != end( whichList ) )
      return false;
    whichList.push_back( std::move( x ) );

    // Rehash; see Section 5.5
    if( ++currentSize > theLists.size( ) )
      rehash( );

    return true;
  }

  bool remove( const HashedObj & x )
  {
    auto & whichList = theLists[ myhash( x ) ];
    auto itr = find( begin( whichList ), end( whichList ), x );

    if( itr == end( whichList ) )
      return false;

    whichList.erase( itr );
    --currentSize;
    return true;
  }

 private:
  vector<list<HashedObj>> theLists;   // The array of Lists
  int  currentSize;

  void rehash( )
  {
    vector<list<HashedObj>> oldLists = theLists;

    // Create new double-sized, empty table
    theLists.resize( nextPrime( 2 * theLists.size( ) ) );
    for( auto & thisList : theLists )
      thisList.clear( );

    theLists.resize( nextPrime( 2 * theLists.size( ) ) );
    for( auto & thisList : theLists )
      thisList.clear( );

    // Copy table over
    currentSize = 0;
    for( auto & thisList : oldLists )
      for( auto & x : thisList )
        insert( std::move( x ) );
  }

  size_t myhash( const HashedObj & x ) const
  {
    static hash<HashedObj> hf;  ***** ERROR HERE *****
    return hf( x ) % theLists.size( );
  }
};

#endif

我的错误:

SeparateChaining.h: In instantiation of ‘size_t OpenHashTable<HashedObj>::myhash(const HashedObj&) const [with HashedObj = std::vector<int>; size_t = long unsigned int]’:

SeparateChaining.h:33:44:   required from ‘bool OpenHashTable<HashedObj>::contains(const HashedObj&) const [with HashedObj = std::vector<int>]’

movetest1.cpp:107:29:   required from here

SeparateChaining.h:106:34: error: ‘std::hash<std::vector<int> > hf’ has incomplete type
 static hash<HashedObj> hf;
                        ^

我该如何解决这个问题? 如果我的描述没有意义或需要清晰,请告诉我。提前致谢!

1 个答案:

答案 0 :(得分:0)

原因是除了std::hash之外,std::vector没有定义std::vector<bool>。它仅针对basic types and select library types定义。您必须实现自己的散列算法。

关于您的上一条评论,hash( x )是无效代码,因为std::hash是一个类模板,而不是一个函数模板。

您也无法为std::hash<std::vector<int>>编写自己的专精,因为std::vector<int>不是用户定义的类型。

适当的解决方案将采用C++ standard library - OpenHashTable的方式,应允许其用户指定散列算法:

template<typename HashedObj, typename Hash = std::hash<HashedObj>>
class OpenHashTable {
    // ...
    size_t myhash(const HashedObj& x) const {
        static Hash hf;
        return hf(x) % theLists.size();
    }
};

所以你可以按如下方式使用它:

struct my_vector_int_hash {
    size_t operator()(const std::vector<int>& v) const {
        // your code here
    }
};

OpenHashTable<std::vector<int>, my_vector_int_hash> hashtable;

更新:只要讨论是否可以专攻std::hash<std::vector<int>>,这就是为什么不允许你这样做的原因。

[namespace.std]/1说:

  

如果C ++程序向名称空间std添加声明或定义,或者在命名空间std中添加名称空间,则未定义C ++程序的行为,除非另有说明。只有当声明取决于用户定义的类型且专业化符合原始模板的标准库要求且未明确禁止时,程序才可以将任何标准库模板的模板特化添加到命名空间std

std::vector<int>不是用户定义的类型,也不依赖于任何用户定义的类型,因此这种特殊化是非法的,会导致未定义的行为。