c_cpp C中的哈希表环境类

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c_cpp C中的哈希表环境类相关的知识,希望对你有一定的参考价值。

#ifndef XEN_ENV_H
#define XEN_ENV_H

#ifdef __cplusplus
extern "C" {
#endif

//container structure for variable environment
struct XenEnvBox
{
    char* key;
    XenObject* obj;
    struct XenEnvBox* link;
};

typedef struct XenEnvBox XenEnvBox;

#define XenEnvBox_SET_NULL_OL(xeb) do {\
                    xeb->obj = NULL; \
                    xeb->key = NULL; \
                    xeb->link = NULL;}while(0)
                    
#define XenEnvBox_SET_NULL_O(xeb) xeb->obj = NULL

#define XenEnvBox_SET_NULL_L(xeb) xeb->link = NULL 

#define XenEnvBox_IS_NULL_O(xeb) xeb->obj == NULL

#define XenEnvBox_IS_NULL_L(xeb) xeb->link == NULL

#define XenEnvBox_FIND_EMPTY(xeb) while(xeb->link != NULL) xeb = xeb->link

#define XenEnvBox_KEY_CMP(key, hskey) hskey != NULL && (strcmp(key, hskey) == 0)

XenEnvBox* XenEnvBox_new(char* key, XenObject* xo);

void XenEnvBox_set_null(XenEnvBox* xeb);

void XenEnvBox_add_obj(XenEnvBox* xeb, char* key, XenObject* xo);

void XenEnvBox_del(XenEnvBox* xeb);

#define XenEnv_SIZE 5000

#define XenEnv_LOAD_FACTOR(xenv) xenv->ocount / 5000



typedef struct
{
    XenEnvBox* table;
    int size; //current size
    int icount; //total items
    int ocount; //buckets occupied
} XenEnv;
 
XenEnv* XenEnv_new();

//primary hash function for env
unsigned long XenEnv_hash(char *str);

XenObject* XenEnv_insert(XenEnv* xe, char* key, XenObject* xo);

XenObject* XenEnv_find(XenEnv* xe, char* key);

void XenEnv_del(XenEnv* xe, char* key);

void XenEnv_expand(XenEnv* xe);



#ifdef __cplusplus
}
#endif

#include "Xenon.h"



XenEnvBox* XenEnvBox_new(char* key, XenObject* xo)
{
    XenEnvBox* xeb = malloc(sizeof(XenEnvBox));
    xeb->key = malloc(strlen(key));
    strcpy(xeb->key, key);
    xeb->obj = xo;
    xeb->link = NULL; 
    return xeb;
}


//once a hash slot is found, either chains or inserts the pair into this box
void XenEnvBox_add_obj(XenEnvBox* xeb, char* key, XenObject* xo)
{
    if(xeb->key == NULL)
    {
        xeb->obj = xo;
        xeb->key = malloc(strlen(key));
        strcpy(xeb->key, key);
    }
    else 
    {
        if(XenEnvBox_KEY_CMP(key, xeb->key))
        {
            xeb->obj = xo;
            return;
        }
        while(xeb->link != NULL)
        {
            xeb = xeb->link;
            //checks if name is reassigned, and changes XenObject pointer
            if(XenEnvBox_KEY_CMP(key, xeb->key))
            {
                xeb->obj = xo;
                return;
            }
        }
        //creates new chain link if space occupied
        xeb->link = XenEnvBox_new(key, xo);
    }
}


//deletes entire xenenvbox
void XenEnvBox_del(XenEnvBox* xeb)
{
    if(xeb->key != NULL) free(xeb->key);
    if(xeb->obj != NULL) XenGc_del(xeb->obj);
    if(xeb->link != NULL) XenEnvBox_del(xeb->link);
    free(xeb);
}

XenEnv* XenEnv_new()
{
    XenEnv* env = malloc(sizeof(XenEnv));
    env->ocount = 0;
    env->icount = 0;
    env->size = XenEnv_SIZE;
    env->table = malloc(sizeof(XenEnvBox) * XenEnv_SIZE);
    return env;
}

unsigned long
XenEnv_hash(char *str)
{
    unsigned long hash = 5381;
    int c;

    while ((c = *str++))
        hash = ((hash << 5) + hash) + c; /* hash * 33 + c */

    return hash;    
}

XenObject* XenEnv_insert(XenEnv* xe, char* key, XenObject* xo)
{
    if(xe->icount > (xe->size - 100)) XenEnv_expand(xe);
    XenEnvBox* hashslot = (xe->table) + (XenEnv_hash(key) % xe->size);
    if(XenEnvBox_IS_NULL_O(hashslot)) xe->ocount++;
    XenEnvBox_add_obj(hashslot, key, xo);
    xe->icount++;
    return xo;
}

//finds a variable in the table
XenObject* XenEnv_find(XenEnv* xe, char* key)
{
    XenEnvBox* hashslot = (xe->table) + (XenEnv_hash(key) % xe->size);
    while(hashslot != NULL)
    {
        if(XenEnvBox_KEY_CMP(key, hashslot->key))
        {
            return hashslot->obj;
        }
        else
        {
            hashslot = hashslot->link;
        }
    }
    //todo: decide if error handling
    return (XenObject*)XenNone_new();
}

//deletes a hashslots data and key
void XenEnv_del(XenEnv* xe, char* key)
{
    XenEnvBox* hashslot = (xe->table) + (XenEnv_hash(key) % xe->size);
    if(XenEnvBox_KEY_CMP(key, hashslot->key))
    {
        free(hashslot->key);
        hashslot->key = NULL;
        XenGc_del(hashslot->obj);
        hashslot->obj = NULL;
        xe->ocount--;
        xe->icount--;
    }
    //works off the link incase of downstream chain items
    else while(hashslot->link != NULL)
    {
        if(XenEnvBox_KEY_CMP(key, hashslot->link->key))
        {
            if(hashslot->link->key != NULL) free(hashslot->link->key);
            if(hashslot->link->obj != NULL) XenGc_del(hashslot->link->obj);
            free(hashslot->link);
            xe->icount--;
            hashslot->link = hashslot->link->link;
        }
        hashslot = hashslot->link;
    }
}

//expands the variable table size
void XenEnv_expand(XenEnv* xe)
{
    xe->size += xe->size;
    xe->table = realloc(xe->table, sizeof(XenEnvBox) * xe->size);
}

#endif

以上是关于c_cpp C中的哈希表环境类的主要内容,如果未能解决你的问题,请参考以下文章

c_cpp 在C中的哈希表,它可以解决重复问题。

c_cpp c的哈希表

c_cpp 哈希表实现

c_cpp 为字符串实现哈希表和哈希函数

c_cpp 为字符串实现哈希表和哈希函数

c_cpp c中非常简单的哈希表