(第五章 1)组合——从DList到HashTable

       在HashTable中,用到了DList来解决冲突,我们不用重新实现其内部的DList,只需将已经实现的双向链表DList组合到HashTable中使用即可。下面给出工程的全部代码:


(第五章 1)组合——从DList到HashTable
就不再解释其中每个文件干嘛的了,我懂的。 依次来看看:

 

1. Makefile
(第五章 1)组合——从DList到HashTable
-D name: Predefine name as a macro. (man gcc可以看到)

 

2. typedef.h

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

#ifndef TYPEDEF_H
#define TYPEDEF_H

typedef enum _Ret
{
	RET_OK,
	RET_OOM,
	RET_STOP,
	RET_INVALID_PARAMS,
	RET_FAIL
}Ret;

typedef void     (*DataDestroyFunc)(void* ctx, void* data);
typedef int      (*DataCompareFunc)(void* ctx, void* data);
typedef Ret      (*DataVisitFunc)(void* ctx, void* data);
typedef int       (*DataHashFunc)(void* data);

#ifdef __cplusplus
#define DECLS_BEGIN extern "C" {
#define DECLS_END   }
#else
#define DECLS_BEGIN
#define DECLS_END
#endif/*__cplusplus*/

#define return_if_fail(p) if(!(p)) \
	{printf("%s:%d Warning: "#p" failed.\n", \
		__func__, __LINE__); return;}
#define return_val_if_fail(p, ret) if(!(p)) \
	{printf("%s:%d Warning: "#p" failed.\n",\
	__func__, __LINE__); return (ret);}

#define SAFE_FREE(p) if(p != NULL) {free(p); p = NULL;}

typedef Ret (*SortFunc)(void** array, size_t nr, DataCompareFunc cmp);

#endif/*TYPEDEF_H*/

 

 

3. hash_table.h

#include <stdio.h>
#include "typedef.h"

#ifndef HASH_TABLE_H
#define HASH_TABLE_H

DECLS_BEGIN

struct _HashTable;
typedef struct _HashTable HashTable;

HashTable* hash_table_create(DataDestroyFunc data_destroy, void* ctx, DataHashFunc hash, int slot_nr);

size_t   hash_table_length(HashTable* thiz);
Ret      hash_table_insert(HashTable* thiz, void* data);
Ret      hash_table_delete(HashTable* thiz, DataCompareFunc cmp, void* data);
Ret      hash_table_find(HashTable* thiz, DataCompareFunc cmp, void* data, void** ret_data);
Ret      hash_table_foreach(HashTable* thiz, DataVisitFunc visit, void* ctx);

void hash_table_destroy(HashTable* thiz);

DECLS_END

#endif/*HASH_TABLE*/

 

 

4.hash_table.c

#include "dlist.h"
#include "hash_table.h"

struct _HashTable
{
	DataHashFunc    hash;
	DList**         slots;
	size_t          slot_nr;
	DataDestroyFunc data_destroy;
	void*           data_destroy_ctx;
};

HashTable* hash_table_create(DataDestroyFunc data_destroy, void* ctx, DataHashFunc hash, int slot_nr)
{
	HashTable* thiz = NULL;

	return_val_if_fail(hash != NULL && slot_nr > 1, NULL);
	
	thiz = (HashTable*)malloc(sizeof(HashTable));

	if(thiz != NULL)
	{
		thiz->hash = hash;
		thiz->slot_nr  = slot_nr;
		thiz->data_destroy_ctx = ctx;
		thiz->data_destroy = data_destroy;
		if((thiz->slots = (DList**)calloc(sizeof(DList*)*slot_nr, 1)) == NULL)
		{
			free(thiz);
			thiz = NULL;
		}
	}

	return thiz;
}

Ret      hash_table_insert(HashTable* thiz, void* data)
{
	size_t index = 0;

	return_val_if_fail(thiz != NULL, RET_INVALID_PARAMS);

	index = thiz->hash(data)%thiz->slot_nr;
	if(thiz->slots[index] == NULL)
	{
		thiz->slots[index] = dlist_create(thiz->data_destroy, thiz->data_destroy_ctx);
	}

	return dlist_prepend(thiz->slots[index], data);
}

Ret      hash_table_delete(HashTable* thiz, DataCompareFunc cmp, void* data)
{
	int index = 0;
	DList* dlist = NULL;

	return_val_if_fail(thiz != NULL && cmp != NULL, RET_INVALID_PARAMS);

	index = thiz->hash(data)%thiz->slot_nr;
	dlist = thiz->slots[index];
	if(dlist != NULL)
	{
		index = dlist_find(dlist, cmp, data);
	
		return dlist_delete(dlist, index);
	}

	return RET_FAIL;
}

size_t   hash_table_length(HashTable* thiz)
{
	size_t i = 0;
	size_t nr = 0;

	return_val_if_fail(thiz != NULL, 0);

	for(i = 0; i < thiz->slot_nr; i++)
	{
		if(thiz->slots[i] != NULL)
		{
			nr += dlist_length(thiz->slots[i]);
		}
	}

	return nr;
}

Ret    hash_table_find(HashTable* thiz, DataCompareFunc cmp, void* data, void** ret_data)
{
	int index = 0;
	DList* dlist = NULL;
	return_val_if_fail(thiz != NULL && cmp != NULL && ret_data != NULL, RET_INVALID_PARAMS);
	
	index = thiz->hash(data)%thiz->slot_nr;
	dlist = thiz->slots[index];
	if(dlist != NULL)
	{
		index = dlist_find(dlist, cmp, data);

		return dlist_get_by_index(dlist, index, ret_data);
	}

	return RET_FAIL;
}

Ret      hash_table_foreach(HashTable* thiz, DataVisitFunc visit, void* ctx)
{
	size_t i = 0;
	
	return_val_if_fail(thiz != NULL && visit != NULL, RET_INVALID_PARAMS);

	for(i = 0; i < thiz->slot_nr; i++)
	{
		if(thiz->slots[i] != NULL)
		{
			dlist_foreach(thiz->slots[i], visit, ctx);
		}
	}

	return RET_OK;
}

void hash_table_destroy(HashTable* thiz)
{
	size_t i = 0;

	if(thiz != NULL)
	{
		for(i = 0; i < thiz->slot_nr; i++)
		{
			if(thiz->slots[i] != NULL)
			{
				dlist_destroy(thiz->slots[i]);
				thiz->slots[i] = NULL;
			}
		}

		free(thiz->slots);
		free(thiz);
	}

	return;
}

#ifdef HASH_TABLE_TEST
#include "test_helper.c"

int main(int argc, char* argv[])
{
	int i = 0;
	int n = 10000;
	int ret_data = 0;
	HashTable* hash_table = hash_table_create(NULL, NULL, hash_int, 31);

	for(i = 0; i < n; i++)
	{
		assert(hash_table_length(hash_table) == i);
		assert(hash_table_insert(hash_table, (void*)i) == RET_OK);
		assert(hash_table_length(hash_table) == (i + 1));
		assert(hash_table_find(hash_table, cmp_int, (void*)i, (void**)&ret_data) == RET_OK);
		assert(ret_data == i);
	}

	for(i = 0; i < n; i++)
	{
		assert(hash_table_delete(hash_table, cmp_int, (void*)i) == RET_OK);
		assert(hash_table_length(hash_table) == (n - i -1));
		assert(hash_table_find(hash_table, cmp_int, (void*)i, (void**)&ret_data) != RET_OK);
	}
	
	hash_table_destroy(hash_table);

	return 0;
}
#endif/*HASH_TABLE_TEST*/

 

5. 最后来复习一下以前写的几个文件

typedef.h

#include <stdio.h>
#include <assert.h>
#include <stdlib.h>

#ifndef TYPEDEF_H
#define TYPEDEF_H

typedef enum _Ret
{
	RET_OK,
	RET_OOM,
	RET_STOP,
	RET_INVALID_PARAMS,
	RET_FAIL
}Ret;

typedef void     (*DataDestroyFunc)(void* ctx, void* data);
typedef int      (*DataCompareFunc)(void* ctx, void* data);
typedef Ret      (*DataVisitFunc)(void* ctx, void* data);
typedef int       (*DataHashFunc)(void* data);

#ifdef __cplusplus
#define DECLS_BEGIN extern "C" {
#define DECLS_END   }
#else
#define DECLS_BEGIN
#define DECLS_END
#endif/*__cplusplus*/

#define return_if_fail(p) if(!(p)) \
	{printf("%s:%d Warning: "#p" failed.\n", \
		__func__, __LINE__); return;}
#define return_val_if_fail(p, ret) if(!(p)) \
	{printf("%s:%d Warning: "#p" failed.\n",\
	__func__, __LINE__); return (ret);}

#define SAFE_FREE(p) if(p != NULL) {free(p); p = NULL;}

typedef Ret (*SortFunc)(void** array, size_t nr, DataCompareFunc cmp);

#endif/*TYPEDEF_H*/

 

dlist.h

#include <stdio.h>
#include "typedef.h"

#ifndef DLIST_H
#define DLIST_H

DECLS_BEGIN

struct _DList;
typedef struct _DList DList;

DList* dlist_create(DataDestroyFunc data_destroy, void* ctx);

Ret dlist_insert(DList* thiz, size_t index, void* data);
Ret dlist_prepend(DList* thiz, void* data);
Ret dlist_append(DList* thiz, void* data);
Ret dlist_delete(DList* thiz, size_t index);
Ret dlist_get_by_index(DList* thiz, size_t index, void** data);
Ret dlist_set_by_index(DList* thiz, size_t index, void* data);
size_t   dlist_length(DList* thiz);
int      dlist_find(DList* thiz, DataCompareFunc cmp, void* ctx);
Ret      dlist_foreach(DList* thiz, DataVisitFunc visit, void* ctx);

void dlist_destroy(DList* thiz);

DECLS_END

#endif/*DLIST*/

 
 

 

 

你可能感兴趣的:(Hashtable)