scl cmap 的实现

数组bucket_array挂链表的形式,数组的每个下标当着一个hash 值。
一个键hash 完之后,与 数组大小进行取余,得到的数字就是数组的小标,新的节点就往下挂载节点。

#ifndef __CMAP_H__
#define __CMAP_H__
#include "dscommon.h"

#ifdef __cplusplus
extern "C" {
#endif

int key_cmp_int(void* key1, void* key2);
int value_cmp_int(void* key1, void* key2);
int hash_func_int(void *key);

#define DEFAULT_BUCKET_SIZE 13  // prime number is better.
enum KEY_TYPE { KEY_TYPE_INT, KEY_TYPE_STR, KEY_TYPE_PTR };
enum VAL_TYPE { VAL_TYPE_INT, VAL_TYPE_STR, VAL_TYPE_PTR };

typedef struct mnode
{
	union key
	{
		int   k_integer; //  整形类型
		void* k_ptr;	 //  指针类型,字符串自己申请
	};

	union val
	{
		int v_integer;
		void* v_ptr;	 //  指针类型,字符串自己申请
	};

	struct mnode* next;
}mnode;

typedef struct cmap_iterator
{
	int index;
	mnode* node;
}cmap_iterator;

typedef struct cmap
{
	int key_type;    // pointer, int string
	int val_type;

	int bucket_size; // arraysize
	mnode* bucket_array; //
	
	int (*key_cmp)(void* key1, void* key2);
	int (*val_cmp)(void* val1, void* val2);
	int (*hash_func)(void *key);
}cmap;

cmap* cmap_create(int key_type, int val_type, int(*key_cmp)(void* key1, void *key2),
	int(*val_cmp)(void* key1, void *key2),
	int(*hash_func)(void* key));

void cmap_init_with_size(cmap* m, int key_type, int val_type, int bucket_size, int (*cmp)(void* key1, void *key2),
	int(*val_cmp)(void* key1, void *key2),
	int(*hash_func)(void* key));

void* cmap_get(cmap* m, void *key);

mnode* cmap_find(cmap* m, void *key);

cmap_iterator* cmap_get_start_pos(cmap* m, cmap_iterator* pos);

cmap_iterator* cmap_get_next(cmap* m, cmap_iterator* pos);

// 1 新值  0, 修改之前的值
int cmap_insert(cmap* m, void* key, void* value);

void cmap_replace_value(cmap* m, mnode* mn, void* newvalue);
void cmap_create_key(cmap* m, mnode* mn, void *key);

void cmap_destroy(cmap* m);

#ifdef __cplusplus
}
#endif
#endif

cmap.c 实现代码如下:

#include "cmap.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

cmap* cmap_create(int key_type, int val_type,
				  int(*key_cmp)(void* key1, void *key2),
				  int(*val_cmp)(void* key1, void *key2),
				  int(*hash_func)(void* key))
{
	cmap* m = (cmap*)malloc(sizeof(cmap));
	cmap_init_with_size(m, key_type, val_type, DEFAULT_BUCKET_SIZE, key_cmp, val_cmp, hash_func);
	return m;
}

void cmap_init_with_size(cmap* m, int key_type, int val_type, int bucket_size, int(*key_cmp)(void* key1, void *key2),
	int(*val_cmp)(void* key1, void *key2),
	int(*hash_func)(void* key))
{
	int i = 0;
	m->key_cmp = key_cmp;
	m->val_cmp = val_cmp;
	m->hash_func = hash_func;

	m->key_type = key_type;
	m->val_type = val_type;

	m->bucket_size = bucket_size;
	m->bucket_array = (mnode*)malloc(m->bucket_size * sizeof(mnode));
	for (i = 0; i < m->bucket_size; ++i)
		m->bucket_array[i].next = NULL;
}

void cmap_set(cmap* m, void *key)
{
	// struct mnode * newnode = (struct mnode*)malloc(sizeof(struct mnode));
	
	if (m->key_type == KEY_TYPE_INT)
	{
		;
	}
}

void* cmap_get(cmap* m, void *key)
{
	int found = 0;
	int idx = m->hash_func(key) % m->bucket_size;
	struct mnode* pre = &m->bucket_array[idx];
	struct mnode* cur = m->bucket_array[idx].next;
	while (cur)
	{
		cur = cur->next;
	}
	return NULL;

}
// 1 新节点  0, 修改之前的值
int cmap_insert(cmap* m, void* key, void* value)
{
	int ret = 0;
	int idx = m->hash_func(key) % m->bucket_size;
	struct mnode* pre = &m->bucket_array[idx];
	struct mnode* cur = pre->next;
	while (cur)
	{
		if (KEY_TYPE_INT == m->key_type)
		{
			if (0 == m->key_cmp(&cur->k_integer, key))
			{
				cmap_replace_value(m, cur, value);
				break;
			}
		}
		else
		{
			if (0 == m->key_cmp(cur->k_ptr, key))
			{
				cmap_replace_value(m, cur, value);
				break;
			}
		}
		pre = cur;
		cur->next;
	}

	if (cur == NULL)
	{
		ret = 1;
		// 新建一个节点插入新的值
		struct mnode *n = (mnode*)malloc(sizeof(mnode));
		n->k_ptr = NULL;
		n->v_ptr = NULL;
		cmap_create_key(m, n, key);
		cmap_replace_value(m, n, value);
		
		pre->next = n;
		n->next = NULL;
	}

	return ret;
}

mnode* cmap_find(cmap* m, void *key)
{
	mnode *ptr = NULL;
	int idx = 0;
	int hash_val = m->hash_func(key);
	idx = hash_val % m->bucket_size;
	mnode* i = m->bucket_array[idx].next;
	while (i)
	{
		if (KEY_TYPE_INT == m->key_type)
		{
			if (m->key_cmp(&i->k_integer, key)==0)
			{
				printf("equal\n");
				ptr = i;
				break;
			}
		}
		else
		{
			if (m->key_cmp(i->k_ptr, key) == 0)
			{
				printf("equal..\n");
				ptr = i;
				break;
			}
		}
			
		i = i->next;
	}

	return ptr;
}

void cmap_replace_value(cmap* m, mnode* mn, void* newvalue)
{
	// 字符串要释放之前的空间
	if (VAL_TYPE_INT == m->val_type)
	{
		mn->v_integer = *(int*)newvalue;
	}
	else if(VAL_TYPE_STR == m->val_type)
	{
		if (mn->v_ptr)
			free(mn->v_ptr);
		int sz = strlen((char*)newvalue) + 1;
		char *v = (char*)malloc(strlen((char*)newvalue) + 1);
		memset(v, 0, sz);
		memcpy(v, (char*)newvalue, sz);
		mn->v_ptr = (void*)v;
	}
	else if (VAL_TYPE_PTR == m->val_type)
	{
		mn->v_ptr = newvalue;
	}
}

void cmap_create_key(cmap* m, mnode* mn, void *key)
{
	if (KEY_TYPE_INT == m->key_type)
	{
		mn->k_integer = *(int*)key;
	}
	else if (KEY_TYPE_STR == m->key_type)
	{
		int sz = strlen((char*)key) + 1;
		char* newkey = (char*)malloc(sz);
		memcpy(newkey, (char*)key, sz);
		mn->k_ptr = (void*)newkey;
	}
	else if (KEY_TYPE_PTR == m->key_type)
	{
		mn->k_ptr = key;
	}
}

void cmap_destroy(cmap* m)
{
	/* 
	1. 先销毁节点定义 中的 k_ptr 和 v_ptr 
	2. 销毁节点
	3. 最后销毁 cmap 
	*/
	int i = 0;
	mnode* mn = NULL;
	mnode* next = NULL;
	mnode* cur = NULL;
	for (i = 0; i < m->bucket_size; ++i)
	{
		mn = &m->bucket_array[i];
		cur = mn->next;
		while (cur)
		{
			next = cur->next;

			if (m->key_type == KEY_TYPE_STR)
			{
				free(cur->k_ptr);
			}
			if (m->val_type == VAL_TYPE_STR)
			{
				free(cur->v_ptr);
			}

			cur = next;
		}
	}

	free(m->bucket_array);
	free(m);
}

cmap_iterator* cmap_get_start_pos(cmap* m, cmap_iterator* pos)
{
	// 找到第一个有值的地方
	// 不存在返回空
	int i = 0;
	mnode* mn = NULL;
	pos->node = NULL;
	for (i = 0; i < m->bucket_size; ++i)
	{
		mn = &m->bucket_array[i];
		if (mn->next)
		{
			(pos)->index = i;
			(pos)->node = mn->next;
			break;
		}
	}

	return pos;
}

cmap_iterator* cmap_get_next(cmap* m, cmap_iterator* pos)
{
	if (NULL == pos || pos->node == NULL)
		return NULL;
	int i = 0;
	int idx = pos->index;
	mnode* cur = pos->node;
	pos->node = NULL;
	if (cur->next)
	{
		pos->node = cur->next;
	}
	else
	{	// 从下一个桶里找。
		for (i = idx + 1; i < m->bucket_size; ++i)
		{
			cur = &m->bucket_array[i];
			if (cur->next)
			{
				pos->index = i;
				pos->node = cur->next;
				break;
			}
		}
	}
	return pos;
}

源码、测试代码地址如下:
https://gitee.com/jesson-deng/xBrain添加链接描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值