字典
字典在很多高级语言里都有,比如
- js的对象结构可以当字典来用
- python的字典
- go的map
- ......................
但是你们知道字典是怎么实现的吗?本文来实现一个简单的字典。
python的字典
先来看python的字典是怎样的
d = {}
d["name"]="biningo"
d["age"] = "19"
name = d.get("name")
age = d.get("age")
c语言实现
参考了Redis的字典结构。字典在redis底层应用非常普遍。因为redis是一个K-V数据库
这里只是实现了string类型的字典,键值都是string
用一个Hash Table来存放键值,线性探测法解决冲突【redis是用拉链法】
dictEntry:存放K-V的结构体
struct dictEntry{
string key;
string val;
};
dict:字典,里面有一个Hash Table
//字典 无序
struct dict{
dictEntry** table; //哈希表数组
int size; //哈希表大小
int len; //键值对计数器
};
根据string来计算Hash Code
//计算str的哈希值 参照java hashCode
int hash(string s){
int h = 0;
for(int i=0;i<s.length();i++){
h = 31 * h + (s[i] & 0xff);
}
return h;
}
创建空字典
dict* dictCreate(int size){
dict* d = (dict*)malloc(sizeof(dict));
d->table = (dictEntry**)calloc(size,sizeof(dictEntry*)); //这里要注意了
for(int i=0;i<size;i++)
d->table[i] = NULL;
d->size = size;//size当作负载因子
d->len=0;
return d;
}
Get、Set
void set(dict* d,string key,string val){
if(d->size==d->len){
cout<<"哈希表满了"<<endl;
return;
}
int index = hash(key)%d->size;
while(d->table[index]!=NULL){
index = (index+1)%d->size;
}
d->table[index] = (dictEntry*)malloc(sizeof(dictEntry)); //先开辟空间
d->table[index]->val = val;
d->table[index]->key = key;
d->len++;
return;
}
string get(dict* d,string key){
if(d->len==0){
cout<<"哈希表空的"<<endl;
return "";
}
int index = hash(key)%d->size;
int c=1;
while( c<d->size){
if(d->table[index] && d->table[index]->key==key)
break;
index = (index+1)%d->size;
c++;
}
if(c<d->size){
d->len--;
return d->table[index]->val;
}
else{
cout<<"找不到元素"<<endl;
return "";
}
}
删除键值
//根据键查找哈希表的索引
int getIndex(dict* d,string key){
if(d->len==0){
cout<<"哈希表空的"<<endl;
return -1;
}
int index = hash(key)%d->size;
int c=1;
while( c<d->size && d->table[index]->key!=key){
index = (index+1)%d->size;
c++;
}
if(c<d->size)
return index;
else{
cout<<"找不到元素"<<endl;
return -1;
}
}
//根据键删除键值对
void DeleteByKey(dict* d,string key){
int i = getIndex(d,key);
if(i>=0){
d->table[i] = NULL;
d->len--;
}
}
完整代码以及示例
#include <iostream>
#include<stdint.h>
using namespace std;
struct dictEntry{
string key;
string val;
};
//字典 无序
struct dict{
dictEntry** table; //哈希表数组
int size; //哈希表大小
int len; //键值对计数器
};
dict* dictCreate(int size){
dict* d = (dict*)malloc(sizeof(dict));
d->table = (dictEntry**)calloc(size,sizeof(dictEntry*)); //这里要注意了
for(int i=0;i<size;i++)
d->table[i] = NULL;
d->size = size;//size当作负载因子
d->len=0;
return d;
}
//计算str的哈希值 参照java hashCode
int hash(string s){
int h = 0;
for(int i=0;i<s.length();i++){
h = 31 * h + (s[i] & 0xff);
}
return h;
}
void set(dict* d,string key,string val){
if(d->size==d->len){
cout<<"哈希表满了"<<endl;
return;
}
int index = hash(key)%d->size;
while(d->table[index]!=NULL){
index = (index+1)%d->size;
}
d->table[index] = (dictEntry*)malloc(sizeof(dictEntry)); //先开辟空间
d->table[index]->val = val;
d->table[index]->key = key;
d->len++;
return;
}
string get(dict* d,string key){
if(d->len==0){
cout<<"哈希表空的"<<endl;
return "";
}
int index = hash(key)%d->size;
int c=1;
while( c<d->size){
if(d->table[index] && d->table[index]->key==key)
break;
index = (index+1)%d->size;
c++;
}
if(c<d->size){
return d->table[index]->val;
}
else{
cout<<"找不到元素"<<endl;
return "";
}
}
//根据键查找哈希表的索引
int getIndex(dict* d,string key){
if(d->len==0){
cout<<"哈希表空的"<<endl;
return -1;
}
int index = hash(key)%d->size;
int c=1;
while( c<d->size && d->table[index]->key!=key){
index = (index+1)%d->size;
c++;
}
if(c<d->size)
return index;
else{
cout<<"找不到元素"<<endl;
return -1;
}
}
//根据键删除键值对
void DeleteByKey(dict* d,string key){
int i = getIndex(d,key);
if(i>=0){
d->table[i] = NULL;
d->len--;
}
}
int main(int argc, char *argv[])
{
dict* d = dictCreate(100);
set(d,"age","1");
set(d,"name","biningo");
cout<<get(d,"one");
cout<<get(d,"age")<<" "<<get(d,"name")<<endl;
DeleteByKey(d,"name");
cout<<get(d,"name")<<endl;
return 0;
}
找不到元素
1 biningo
找不到元素