coding啊coding,有帮忙测试代码的没
lbaby 2007-08-04 01:10:56 平时的工作里需要对很多数据进行查找,数据的格式不定,每新加一个数据
都要写对应的查找接口(程序的构架不好),真累人。
数据大致看起来这样:
f1|f2|f3
fn|fn1|fn2
就是列数固定的 用同样分隔符 分隔的数据
这次要新加很多数据,别说作了,就连事先想一想就够累人的了,于是俺怒了--虽然俺是从乡下来的,但是---俺怒了,新写了一个查找类,可以查找任意列数任意长度(当然了,不能太离谱,因为我们的数据基本上格式是一致的)的数据,可以对第N(非第一列)列定义不同的查找规则(比如说,指定第二比参数大)
其中一部分代码是抄的sgi的stl,水平所限,没法将代码写得更通用:
//hash 查找
//htable.h
#ifndef HASH_TABLE_H
#define HASH_TABLE_H
#include <vector>
#include <stdexcept>
#ifdef _USING_NAMESPACE_STD
using namespace std;
#endif
#ifdef _NEED_STDINT
#include <stdint.h>
#endif
#include <stdio.h>
//To find a data member with your need
template <class T>
class hashvisitor
{
public:
virtual bool done(void)
{
return false;
}
virtual void visit(T *t) =0;
};
//hash function for a string
//
inline size_t hashstr(const char* s)
{
unsigned long h = 0;
for ( ; *s; ++s) {
h = 5*h + *s;
}
return size_t(h);
}
template <class _Key>
struct hash
{ }
;
template<>
struct hash<const char *>
{
size_t operator ()(const char *s)const
{
return (hashstr(s));
}
};
template<>
struct hash<char *>
{
size_t operator ()(char *s)const
{
return (hashstr(s));
}
};
//prime list , for hash table's size
//
enum { num_primes = 28 };
static const unsigned long prime_list[num_primes] =
{
53ul, 97ul, 193ul, 389ul, 769ul,
1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
1610612741ul, 3221225473ul, 4294967291ul
};
//layout for data
//data member's are organized with a chunk of data,
//every data member's size can change with need
//
enum {num_layout = 13};
static const size_t layout_list [ num_layout] =
{
1, 2, 3, 5,
8, 13, 21, 34,
55,89,144,233,377
};
size_t proper_layout(const size_t n);
//note:hash node does not manage data memory itself
//he just point an exist memory region
//obversely , the node is a link list node
template <class T, class HF=hash<T* > >
class hnode
{
public :
hnode( T* v=NULL):m_value(v),m_next(NULL)
{}
virtual void accept(hashvisitor<T> &v)
{
hnode<T> *p = this;
while (!v.done() && p) {
if(!p->m_value) {
break;
}
v.visit(p->m_value);
p = p->m_next;
}
}
size_t hashvalue(void) const
{
return hf(m_value);
}
T * value(void) const
{
return m_value;
}
hnode<T>* back(void)
{
hnode<T>* p = this;
while(p->m_next) {
p= p->m_next;
}
return p;
}
const hnode<T> &
set_next(hnode<T > * h)
{
m_next = h;
return *h;
}
T * set_value(T* v)
{
return m_value = v;
}
private:
HF hf;
T *m_value;
hnode<T> *m_next;
};
//layout infomation for data chunk:
//
typedef struct layout
{
int pos;
size_t len;
bool operator == (const layout &arg) const
{
return (pos == arg.pos) && (len == arg.len);
}
bool operator > (const layout &arg) const
{
return (pos > arg.pos) ||(len > arg.len);
}
bool operator < (const layout &arg) const
{
return (pos < arg.pos) ||(len <arg.len);
}
layout():pos(0),len(0)
{}
}
layout_t;
typedef vector<layout> lo_t;
//this htable can only used to search for data
//never delete any data!
template <class T>
class htable
{
public:
htable(size_t n):size(n),base(NULL),data()
{
size_t i;
for(i = 0 ; i < num_primes; i++) {
if(n <= prime_list[i]) {
break;
}
}
size = (i == num_primes) ? prime_list[i-1]:prime_list[i];
base = new hnode<T> [size];
extra_size = size/4;
}
~htable()
{
purge();
}
void purge(void);
const hnode<T> &insert(const hnode<T> &h);
const hnode<T> & insert(T *h, const vector<layout_t> &l);
hnode<T> &find(const hnode<T> &h);
void set_layout(const vector <layout_t> &l)
{
/*
size_t addn = 0;
for(size_t i = 0 ; i < l.size(); i++){
layout_t nl;
nl.pos += addn;
nl.len = proper_layout(l[i].len);
addn += nl.len -l[i].len;
nl.pos += l[i].pos;
data_layout.push_back( nl );
}*/
data_layout = l;
chunksz = data_layout[data_layout.size() -1] . pos + data_layout[data_layout.size() -1].len;
data.ptr = new uint8_t [size * chunksz];
memset(data.ptr, 0, chunksz * extra_size);
}
const vector <layout_t> & get_layout(void) const
{
return data_layout;
}
htable & operator = ( htable & h);
htable(const htable & h)
{
*this = h;
}
typedef struct pool_info
{
uint8_t *ptr;
size_t count;
pool_info ():ptr(NULL), count(0)
{}
}
data_pool_t ;
private:
size_t h(size_t n)const
{
//printf("%d:%d\n", n, n%size);
return n%size;
}
size_t extra_size ;
//for overflow's extra data
vector <layout_t> data_layout; //
size_t size;//the length of hash table
size_t chunksz;
vector<size_t> base_pool_count;//for hnode's pool count
hnode<T> *base;
data_pool_t data;
vector<hnode<T> *> base_pool;//memory pool for overflow
vector<data_pool_t> data_pool;//data pool for memory manage
};
template <typename T>
class copy_visitor:public hashvisitor<T>
{
public:
copy_visitor(htable <T> *const to,const vector<layout_t> &lo )
:ht(to),l(lo)
{}
virtual void visit(T *t)
{
ht->insert(t, l);
}
private:
vector <layout_t> l;
htable <T> *ht;
};