本程序实现了一个可以插入任意数据对象的c++实现的hash数据库支持增删改查
同时采用了拉链法处理冲突.
接下来我们一起看实现吧
key-value数据库存储单元类型
第一步首先实现一个基础的key-value类型
//field.h
#pragma once
#include <iostream>
class field
{
private:
std::string *key;
void *value;
public:
std::string *getKey();
void *getValue();
void setValue(void *v);
field();
field(std::string *k);
field(std::string *k, void *v);
~field();
};
//field.cpp
#include "field.h"
std::string *field::getKey()
{
return key;
}
void *field::getValue()
{
return value;
}
void field::setValue(void *v)
{
value = v;
}
field::field() : key(NULL), value(NULL) {}
field::field(std::string *k) : key(k), value(NULL) {}
field::field(std::string *k, void *v) : key(k), value(v) {}
field::~field()
{
delete key;
delete value;
}
基于key-value类型的双向链表节点
随后构建一个在类型基础之上的双向链表节点
//doubleLinkedNode.h
#pragma once
#include "field.h"
class doubleLinkedNode
{
private:
doubleLinkedNode *left;
doubleLinkedNode *right;
field *data;
public:
doubleLinkedNode *getLeft();
doubleLinkedNode *getRight();
field *getData();
void setLeft(doubleLinkedNode *p);
void setRight(doubleLinkedNode *p);
void setData(void *v);
doubleLinkedNode();
doubleLinkedNode(field *v);
doubleLinkedNode(std::string *k);
doubleLinkedNode(std::string *k, void *v);
~doubleLinkedNode();
};
//doubleLinkedNode.cpp
#include "doubleLinkedNode.h"
doubleLinkedNode *doubleLinkedNode::getLeft()
{
return left;
}
doubleLinkedNode *doubleLinkedNode::getRight()
{
return right;
}
field *doubleLinkedNode::getData()
{
return data;
}
void doubleLinkedNode::setLeft(doubleLinkedNode *p)
{
left = p;
}
void doubleLinkedNode::setRight(doubleLinkedNode *p)
{
right = p;
}
void doubleLinkedNode::setData(void *v)
{
data->setValue(v);
}
doubleLinkedNode::doubleLinkedNode() : data(NULL) {}
doubleLinkedNode::doubleLinkedNode(field *v) : data(v) {}
doubleLinkedNode::doubleLinkedNode(std::string *k) : data(new field(k)) {}
doubleLinkedNode::doubleLinkedNode(std::string *k, void *v) : data(new field(k, v)){};
doubleLinkedNode::~doubleLinkedNode()
{
delete data;
}
基于双向链表节点构建双向链表
//doubleLinked.h
#pragma once
#include "doubleLinkedNode.h"
#include "observers.h"
class doubleLinked
{
private:
/* data */
doubleLinkedNode *head, *tail;
unsigned int size;
observers *observer;
public:
doubleLinkedNode *find(std::string *key);
bool _insert(std::string *key, void *value);
bool _update(std::string *key, void *value);
bool _delete(std::string *key);
void *_select(std::string *key);
unsigned int getSize();
void creatObserver(observers *obs);
doubleLinked();
~doubleLinked();
};
//doubleLinked.cpp
#include "doubleLinked.h"
doubleLinkedNode *doubleLinked::find(std::string *key)
{
doubleLinkedNode *it = head->getRight();
doubleLinkedNode *end = tail;
while (it != end && *key != *it->getData()->getKey())
{
it = it->getRight();
}
return it;
}
bool doubleLinked::_insert(std::string *key, void *value)
{
doubleLinkedNode *it = find(key);
if (it == tail)
{
doubleLinkedNode *insertObject = new doubleLinkedNode(key, value);
insertObject->setRight(tail);
insertObject->setLeft(tail->getLeft());
tail->getLeft()->setRight(insertObject);
tail->setLeft(insertObject);
size++;
if(observer!=NULL)
observer->flagAdd();
}
return true;
}
bool doubleLinked::_update(std::string *key, void *value)
{
doubleLinkedNode *it = find(key);
if (it == tail)
return false;
it->setData(value);
return true;
}
bool doubleLinked::_delete(std::string *key)
{
doubleLinkedNode *it = find(key);
if (it != tail)
{
it->getLeft()->setRight(it->getRight());
it->getRight()->setLeft(it->getLeft());
size--;
if(observer!=NULL)
observer->flagSub();
delete it;
}
return true;
}
void *doubleLinked::_select(std::string *key)
{
doubleLinkedNode *it = find(key);
if (it == tail)
return NULL;
return it->getData()->getValue();
}
unsigned int doubleLinked::getSize()
{
return size;
}
void doubleLinked::creatObserver(observers *obs)
{
observer = obs;
}
doubleLinked::doubleLinked() : head(new doubleLinkedNode()), tail(new doubleLinkedNode()), size(0)
{
head->setRight(tail);
tail->setLeft(head);
}
doubleLinked::~doubleLinked()
{
doubleLinkedNode *de = head;
doubleLinkedNode *it = head->getRight();
while (it != tail)
{
delete de;
de = it;
it = it->getRight();
}
delete de;
delete it;
}
基于双向链表实现存储的hash结构
//hashTable.h
#pragma once
#include "doubleLinked.h"
class hashTable : public dataBase
{
private:
unsigned int tableSize;
std::hash<std::string> strHash;
std::hash<unsigned long> longHash;
doubleLinked *table;
public:
hashTable(unsigned int size);
~hashTable();
unsigned int hashMapping(std::string *s);
bool __insert__(void *key, void *value);
bool __update__(void *key, void *value);
bool __delete__(void *key);
void *__select__(void *key);
unsigned int __getSize__();
};
//hashTable.cpp
#include "hashTable.h"
hashTable::hashTable(unsigned int size) : tableSize(size), table(new doubleLinked[size])
{
for (unsigned int i = 0; i < size; i++)
{
table[i].creatObserver(&counter);
}
};
hashTable::~hashTable()
{
delete table;
}
unsigned int hashTable::hashMapping(std::string *s)
{
unsigned long temp = strHash(*s);
temp = longHash(temp);
return temp % tableSize;
}
bool hashTable::__insert__(void *k, void *value)
{
std::string *key = static_cast<std::string *>(k);
unsigned int hash = hashMapping(key);
return table[hash]._insert(key, value);
}
bool hashTable::__update__(void *k, void *value)
{
std::string *key = static_cast<std::string *>(k);
unsigned int hash = hashMapping(key);
return table[hash]._update(key, value);
}
bool hashTable::__delete__(void *k)
{
std::string *key = static_cast<std::string *>(k);
unsigned int hash = hashMapping(key);
return table[hash]._delete(key);
}
void *hashTable::__select__(void *k)
{
std::string *key = static_cast<std::string *>(k);
unsigned int hash = hashMapping(key);
return table[hash]._select(key);
}
unsigned int hashTable::__getSize__()
{
return counter.getFlag();
}
构建所有数据对象公有的接口
//dataBase.h
#pragma once
#include <iostream>
#include "observers.h"
class dataBase
{
protected:
observers counter;
public:
virtual bool __insert__(void *key, void *value) = 0;
virtual bool __update__(void *key, void *value) = 0;
virtual bool __delete__(void *key) = 0;
virtual void *__select__(void *key) = 0;
virtual unsigned int __getSize__() = 0;
virtual ~dataBase(){};
};
观察者负责记录数据库有多少个数据对象
//observers.h
#pragma once
class observers
{
private:
int flag;
public:
observers();
int getFlag();
void flagAdd();
void flagSub();
};
//observers.cpp
#include "observers.h"
observers::observers() : flag(0) {}
int observers::getFlag()
{
return flag;
}
void observers::flagAdd()
{
flag++;
}
void observers::flagSub()
{
flag--;
}
基于hash表构建数据创建工厂(方便以后扩充存储结构)
//dataBaseFactory.h
#pragma once
#include "dataBase.h"
#include "hashTable.h"
#include "repeatableHashTable.h"
#define __HASHTABLE__ 0
class dataBaseFactory
{
public:
dataBase *createBase(short int model, unsigned int size);
};
//dataBaseFactory.cpp
#include "dataBaseFactory.h"
dataBase *dataBaseFactory::createBase(short int model, unsigned int size)
{
switch (model)
{
case 0:
return new hashTable(size);
default:
return NULL;
}
}
main函数
//mian.cpp
#include "dataBaseFactory.h"
dataBaseFactory *Factory = new dataBaseFactory();
dataBase *table = Factory->createBase(__HASHTABLE__, 20);
table -> __insert__(指向字符串的指针, 指向任意数据对象的指针);
table -> __update__(指向字符串的指针, 指向任意数据对象的指针);
table -> __delete__(指向字符串的指针);
void * data = table -> __select__(指向字符串的指针);
//void指针不能直接使用需要转换成相应的数据对象指针以下用string做示例
std::string * dataStr = static_cast<std::string *>(data);
std::cout << *dataStr << std::endl;