• 哈希技术


    1. 哈希的定义

    在数据元素的存储位置和它的关键字之间建立一个映射关系f,通过f可以直接得到关键字所代表的数据元素

    2. 哈希表

    哈希技术中用于存储数据元素的数据结构

    3. 哈希函数

    哈希技术中的映射关系f

    4. 哈希技术的关键点

    ① 哈希表:哈希技术需要具体的数据结构为基础,如数组、链表、二叉树......

    ②哈希函数:哈希技术需要映射关键字和数据元素的存储位置,依赖于数学运算,如四则运算、逻辑运算、比较......

    5. 哈希的操作

    ① 创建哈希: Hash* Hash_Create();
    ② 销毁哈希: void Hash_Destroy(Hash* hash);
    ③ 清空哈希: void Hash_Clear(Hash* hash);
    ④ 加入键值对: int Hash_Add(Hash* hash, HashKey* key, HashValue* value);
    ⑤ 删除键值对: HashValue* Hash_Remove (Hash* hash, HashKey* key);
    ⑥ 根据建获取值: HashValue* Hash_Get(Hash* hash, HashKey* key);
    ⑦ 获取键值对数目: int Hash_Count(Hash* hash);

    6. 哈希的实现

    哈希表 = 数组 + 链表

    ① DList.h

    #ifndef DLIST_H
    #define DLIST_H
    
    typedef enum _Ret
    {
        RET_OK,
        RET_OOM,
        RET_STOP,
        RET_PARAMS,
        RET_FAIL
    } Ret;
    
    struct _DList;
    typedef struct _DList DList;
    
    typedef void (*DListDataDestroyFunc)(void* ctx, void* data);
    typedef int (*DListDataCompareFunc)(void* ctx, void* data);
    typedef Ret (*DListDataVisitFunc)(void* ctx, void* data);
    
    DList* dlist_create(DListDataDestroyFunc data_destroy, void* data_destroy_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, DListDataCompareFunc cmp, void* ctx);
    Ret dlist_foreach(DList* thiz, DListDataVisitFunc visit, void* ctx);
    
    void dlist_destroy(DList* thiz);
    
    #endif

    ② DList.c

    #include <stdlib.h>
    #include "DList.h"
    
    typedef struct _DListNode
    {
        struct _DListNode* prev;
        struct _DListNode* next;
    
        void* data;
    }DListNode;
    
    struct _DList
    {
        DListNode* first;
        DListDataDestroyFunc data_destroy;
        void* data_destroy_ctx;
    };
    
    static void dlist_destroy_data(DList* thiz, void* data)
    {
        if(thiz->data_destroy != NULL)
        {
            thiz->data_destroy(thiz->data_destroy_ctx, data);
        }
    
        return;
    }
    
    static DListNode* dlist_create_node(DList* thiz, void* data)
    {
        DListNode* node = malloc(sizeof(DListNode));
    
        if(node != NULL)
        {
            node->prev = NULL;
            node->next = NULL;
            node->data = data;
        }
    
        return node;
    }
    
    static void dlist_destroy_node(DList* thiz, DListNode* node)
    {
        if(node != NULL)
        {
            node->next = NULL;
            node->prev = NULL;
            dlist_destroy_data(thiz, node->data);
            free(node);
        }
    
        return;
    }
    
    DList* dlist_create(DListDataDestroyFunc data_destroy, void* data_destroy_ctx)
    {
        DList* thiz = malloc(sizeof(DList));
    
        if(thiz != NULL)
        {
            thiz->first = NULL;
            thiz->data_destroy = data_destroy;
            thiz->data_destroy_ctx = data_destroy_ctx;
        }
    
        return thiz;
    }
    
    static DListNode* dlist_get_node(DList* thiz, size_t index, int fail_return_last)
    {
        DListNode* iter = thiz->first;
    
        while(iter != NULL && iter->next != NULL && index > 0)
        {
            iter = iter->next;
            index--;
        }
    
        if(!fail_return_last)
        {
            iter = index > 0 ? NULL : iter;
        }
    
        return iter;
    }
    
    Ret dlist_insert(DList* thiz, size_t index, void* data)
    {
        DListNode* node = NULL;
        DListNode* cursor = NULL;
    
        if((node = dlist_create_node(thiz, data)) == NULL)
        {
            return RET_OOM; 
        }
    
        if(thiz->first == NULL)
        {
            thiz->first = node;
    
            return RET_OK;
        }
    
        cursor = dlist_get_node(thiz, index, 1);
        
        if(index < dlist_length(thiz))
        {
            if(thiz->first == cursor)
            {
                thiz->first = node;
            }
            else
            {
                cursor->prev->next = node;
                node->prev = cursor->prev;
            }
            node->next = cursor;
            cursor->prev = node;
        }
        else
        {
            cursor->next = node;
            node->prev = cursor;
        }
    
        return RET_OK;
    }
    
    Ret dlist_prepend(DList* thiz, void* data)
    {
        return dlist_insert(thiz, 0, data);
    }
    
    Ret dlist_append(DList* thiz, void* data)
    {
        return dlist_insert(thiz, -1, data);
    }
    
    Ret dlist_delete(DList* thiz, size_t index)
    {
        DListNode* cursor = dlist_get_node(thiz, index, 0);
    
        if(cursor != NULL)
        {
            if(cursor == thiz->first)
            {
                thiz->first = cursor->next;
            }
    
            if(cursor->next != NULL)
            {
                cursor->next->prev = cursor->prev;
            }
    
            if(cursor->prev != NULL)
            {
                cursor->prev->next = cursor->next;
            }
    
            dlist_destroy_node(thiz, cursor);
        }
    
        return RET_OK;
    }
    
    Ret dlist_get_by_index(DList* thiz, size_t index, void** data)
    {
        DListNode* cursor = dlist_get_node(thiz, index, 0);
    
        if(cursor != NULL)
        {
            *data = cursor->data;
        }
    
        return cursor != NULL ? RET_OK : RET_FAIL;
    }
    
    Ret dlist_set_by_index(DList* thiz, size_t index, void* data)
    {
        DListNode* cursor = dlist_get_node(thiz, index, 0);
    
        if(cursor != NULL)
        {
            cursor->data = data;
        }
    
        return cursor != NULL ? RET_OK : RET_FAIL;
    }
    
    size_t   dlist_length(DList* thiz)
    {
        size_t length = 0;
        DListNode* iter = thiz->first;
    
        while(iter != NULL)
        {
            length++;
            iter = iter->next;
        }
    
        return length;
    }
    
    Ret dlist_foreach(DList* thiz, DListDataVisitFunc visit, void* ctx)
    {
        Ret ret = RET_OK;
        DListNode* iter = thiz->first;
    
        while(iter != NULL && ret != RET_STOP)
        {
            ret = visit(ctx, iter->data);
    
            iter = iter->next;
        }
    
        return ret;
    }
    
    int      dlist_find(DList* thiz, DListDataCompareFunc cmp, void* ctx)
    {
        int i = 0;
        DListNode* iter = thiz->first;
    
        while(iter != NULL)
        {
            if(cmp(ctx, iter->data) == 0)
            {
                break;
            }
            i++;
            iter = iter->next;
        }
    
        return i;
    }
    
    void dlist_destroy(DList* thiz)
    {
        DListNode* iter = thiz->first;
        DListNode* next = NULL;
    
        while(iter != NULL)
        {
            next = iter->next;
            dlist_destroy_node(thiz, iter);
            iter = next;
        }
    
        thiz->first = NULL;
        free(thiz);
    
        return;
    }

    ③ HashTable.h

    #ifndef HASHTABLE_H_
    #define HASHTABLE_H_
    
    #include "DList.h"
    
    typedef int(*DataHashFunc)(void* data);
    
    typedef DListDataDestroyFunc DataDestroyFunc;
    
    typedef DListDataCompareFunc DataCompareFunc;
    
    typedef DListDataVisitFunc DataVisitFunc;
    
    typedef struct HashTable_
    {
        DataHashFunc hashFunc;
        DList** slots;
        int slotNr;
        DataDestroyFunc dataDestroy;
        void* dataDestroyCtx;
    } HashTable;
    
    HashTable* HashTableCreate(DataDestroyFunc dataDestroy, void* ctx, DataHashFunc hashFunc, int slotNr);
    
    Ret HashTableInsert(HashTable* hashTable, void* data);
    
    Ret HashTableDelete(HashTable* hashTable, DataCompareFunc cmp, void* data);
    
    Ret HashTableFind(HashTable* hashTable, DataCompareFunc cmp, void* data, void** retData);
    
    int HashTableLength(HashTable* hashTable);
    
    Ret HashTableForeach(HashTable* hashTable, DataVisitFunc visit, void* ctx);
    
    void HashTableDestroy(HashTable* hashTable);
    
    
    #endif

    ④ HashTable.c

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include "HashTable.h"
    
    HashTable* HashTableCreate(DataDestroyFunc dataDestroy, void* ctx, DataHashFunc hashFunc, int slotNr)
    {
        HashTable* pNewHashTable = (HashTable*)malloc(sizeof(HashTable));
        
        if(pNewHashTable != NULL)
        {
            pNewHashTable->hashFunc = hashFunc;
            pNewHashTable->slotNr = slotNr;
            pNewHashTable->dataDestroy = dataDestroy;
            pNewHashTable->dataDestroyCtx = ctx;
            
            pNewHashTable->slots = (DList**)malloc(slotNr * sizeof(DList*));
            if(pNewHashTable->slots != NULL)
            {
                memset(pNewHashTable->slots, 0, (slotNr * sizeof(DList*)));
            }
            else
            {
                free(pNewHashTable);
                pNewHashTable = NULL;
            }
        }
        
        return pNewHashTable;
    }
    
    Ret HashTableInsert(HashTable* hashTable, void* data)
    {
        Ret ret = RET_FAIL;
        int index = 0;
        
        if(hashTable != NULL)
        {
            index = hashTable->hashFunc(data) % hashTable->slotNr;
            
            if(hashTable->slots[index] == NULL)
            {
                hashTable->slots[index] = dlist_create(hashTable->dataDestroy, hashTable->dataDestroyCtx);
            }
            
            dlist_append(hashTable->slots[index], data);
            
            ret = RET_OK;
        }
        
        return ret;
    }
    
    Ret HashTableDelete(HashTable* hashTable, DataCompareFunc cmp, void* data)
    {
        Ret ret = RET_FAIL;
        int index = 0;
        DList* dList = NULL;
        
        if(hashTable != NULL)
        {
            index = hashTable->hashFunc(data) % hashTable->slotNr;
            
            dList = hashTable->slots[index];
            
            if(dList != NULL)
            {
                index = dlist_find(dList, cmp, data);
                
                dlist_delete(dList, index);
                
                ret = RET_OK;
            }
        }
        
        return ret;
    }
    
    Ret HashTableFind(HashTable* hashTable, DataCompareFunc cmp, void* data, void** retData)
    {
        Ret ret = RET_FAIL;
        int index = 0;
        DList* dList = NULL;
        
        if(hashTable != NULL && cmp != NULL && data != NULL && retData != NULL)
        {
            index = hashTable->hashFunc(data) % hashTable->slotNr;
            
            dList = hashTable->slots[index];
            
            if(dList != NULL)
            {
                index = dlist_find(dList, cmp, data);
                
                dlist_get_by_index(dList, index, retData);
                
                ret = RET_OK;
            }
        }
        
        return ret;
        
    }
    
    int HashTableLength(HashTable* hashTable)
    {
        int sum = 0;
        int index = 0;
        
        if(hashTable != NULL)
        {
            for(index = 0; index < hashTable->slotNr; index++)
            {
                if(hashTable->slots[index] != NULL)
                {
                    sum = sum + dlist_length(hashTable->slots[index]);
                }
            }
        }
        
        return sum;
    }
    
    Ret HashTableForeach(HashTable* hashTable, DataVisitFunc visit, void* ctx)
    {
        int index = 0;
        
        if(hashTable != NULL)
        {
            for(index = 0; index < hashTable->slotNr; index++)
            {
                if(hashTable->slots[index] != NULL)
                {
                    dlist_foreach(hashTable->slots[index], visit, ctx);
                }
            }
        }
        
        return RET_OK;
    }
    
    void HashTableDestroy(HashTable* hashTable)
    {
        int index = 0;
        if(hashTable != NULL)
        {
            if(hashTable->slots != NULL)
            {
                for(index = 0; index < hashTable->slotNr; index++)
                {
                    if(hashTable->slots[index] != NULL)
                    {
                        dlist_destroy(hashTable->slots[index]);
                        hashTable->slots[index] = NULL;
                    }
                }
                
                free(hashTable->slots);
                hashTable->slots = NULL;    
            }
            
            free(hashTable);
            hashTable = NULL;
        }    
    }

    注:数组是最简单的哈希实现

  • 相关阅读:
    如何在dede栏目设置中添加自定义字段(dede二次开发-纯抄贴)
    dedecms内容页 上下篇 添加文章描述方法
    关于透明层----背景透明字不透明的效果
    什么是JavaScript闭包终极全解之一——基础概念
    phpcms v9中调用多栏目的方法--get标签(备实例)
    PHP识别电脑还是手机访问网站
    PHP中 post 与get的区别 详细说明
    js 处理数据里面的空格
    mysql中的unix_timestamp函数
    PHP中date函数月和日带0问题
  • 原文地址:https://www.cnblogs.com/wulei0630/p/9351056.html
Copyright © 2020-2023  润新知