在HashTable中,用到了DList来解决冲突,我们不用重新实现其内部的DList,只需将已经实现的双向链表DList组合到HashTable中使用即可。下面给出工程的全部代码:
就不再解释其中每个文件干嘛的了,我懂的。 依次来看看:
1. Makefile
-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*/
相关推荐
1. 构造函数`Dlist()`通常初始化为空链表,头尾指针为`nullptr`,大小为0。 2. 析构函数`~Dlist()`需要负责释放链表中的所有节点,防止内存泄漏。 3. `insert(int value, int index)`函数在指定位置插入新值,需要...
第first和last操作是最坏情况 O(n)。 to_list也是 O(n) 最坏的情况。 alias Dlist . Dequedeque = Deque . newdeque = Deque . append (deque, 2 )deque = Deque . append (deque, 3 )deque = Deque . prepend ...
Dlist.cpp
import Data.DList -- 创建一个差异列表,表示在任何列表后面添加1,2,3 dl = singleton 1 <> singleton 2 <> singleton 3 -- 将差异列表应用于空列表,得到[1,2,3] normalList = execDList dl [] -- 使用差异列表...
在C/C++中,这个过程可能涉及到遍历链表,查找满足特定条件的节点,然后从链表中移除这些节点。这涉及到对链表结构的深入理解和操作,包括节点的指针操作和内存管理。 在提供的压缩包中,"Dlist2.c"可能是源代码...
dlist(未经测试) 用 Javascript 编写的双向链表数据结构。 这是一个 Javascript 和伪经典模式的实验。列表([元素...]) 列表取决于ddict字典对象。 继承的字典方法用于管理 List 状态: seed, cursor并允许使用...
dlist = os.listdir(dir1) os.mkdir(dir2) for f in dlist: file1 = os.path.join(dir1, f) file2 = os.path.join(dir2, f) if os.path.isfile(file1): mycopy(file1, file2) elif os.path.isdir(file1): ...
6. **Week5-Object_Oriented_Programming**:第五周专注于面向对象编程,包含多个与"DList"相关的文件,如"DList_5.m", "DList_v5.m", "DList.m", "DList_6.m", "DList_v6.m"。这些可能是实现双链表的不同版本,展示...
本次实验的主要目的是理解和掌握线性数据结构——双端队列(Double-Ended Queue,简称deque)的实现与应用。通过实际编程,加深对双端队列特性的理解,如其在头部和尾部进行插入和删除操作的灵活性。同时,将双端...
1. **插入到链表的第一个结点之前**:此时新结点将成为链表的新头部。 2. **插入到链表的末尾**:此时新结点将成为链表的新尾部。 3. **插入到链表的中间某个位置**:在这种情况下,需要更新前后的结点指针以正确...
1、在.net2005 studio中,添加新控件,将下载到本地的jwork.dll加至工具箱中。 2、Jpage分页会默认读取web.config配置文件中,名为data的连接字符串。 ;uid=sa;pwd=1234;database=...
通过上述内容的学习,我们可以了解到MATLAB在图像批量读取方面的基本操作流程及其相关的高级技巧。这对于从事图像处理领域的研究人员来说是非常实用的知识点。未来还可以根据实际需求进一步扩展,例如添加图像的...
【标题】中的“androidjava源码下载-dlist_api”表明这是一个与Android开发相关的Java源代码库,名为“dlist_api”。这个项目可能是为Android应用程序提供特定功能或服务的一个库,可能涉及数据列表的处理和展示。 ...
在配置Bean对象时,有时候它的成员变量是一个list集合或者是一个map,对于list和map有另外的语法。有兴趣可关注本博客:https://blog.csdn.net/qq_40634846,有循序渐进的spring,零基础入门。
`DataList`可以绑定到任何实现了`IEnumerable`接口的数据源,例如数据库查询结果、数组或列表。在`DataList`的模板中,嵌入一个`DropDownList`控件,这样每个`DataList`项都会有一个独立的下拉列表。 ```aspx ...
DObject提供了诸如流输出、流输入、保存到文件和从文件加载数据的基本功能。 3. **线性表**: - **DList**: DList是线性表逻辑类,作为具体存储类型线性表的基类,封装了底层操作接口。DList类具有以下成员方法...
切片:方便截取list、tuple、字符串部分索引的内容 正序切片 语法:dlist = doList[0:3]表示,从索引0开始取,直到索引3为止,但不包括索引3。...语法:slist = dolist[-2:] 表示,从倒数第2个索引开始,取到索引为
在这里,当用户点击按钮时,`big.gotoAndPlay(1)` 会使得影片剪辑 `big` 从第一帧开始播放。 4. **AS与XML交互**: - `System.useCodepage = true;` 设置为true可以确保XML数据中的中文字符正确显示,避免编码问题...
如果存在某个共同的关键字段(即表A的第i列与表B的第j列相等),那么可以通过简单的自然连接来生成一个新的表C,其中包含了满足连接条件的所有记录组合。 #### 实验内容 ##### 3.1 创建与管理线性表 - **创建...
<img src="images/item1.jpg" alt="Item 1"> 这是项目1的描述 <!-- 更多列表项 --> ``` 接下来,`css`目录下的CSS文件用于定义列表的样式,包括3D变换前后的样式。例如,我们可以为`#my3DList`设置基础...