字典

字典在很多高级语言里都有,比如

  1. js的对象结构可以当字典来用
  2. python的字典
  3. go的map
  4. ......................

但是你们知道字典是怎么实现的吗?本文来实现一个简单的字典。

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
找不到元素
posted @ 2020-03-23 22:26  jkjkjkjkjkjk  阅读(262)  评论(0编辑  收藏  举报