哈希表实现

4 篇文章 0 订阅
4 篇文章 1 订阅
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

typedef struct _struct_hash_key
{
    unsigned int uiIp;
    unsigned int uiTeid;
} struct_hash_key;

typedef struct _struct_hash_node
{
    struct _struct_hash_node *pstNext;
    struct _struct_hash_key stKey;
    unsigned long long u64_timeout;
} struct_hash_node;

typedef struct _struct_bucket
{
    unsigned int uiBucketLen;
    struct _node *pstHead;
} struct_bucket;

typedef struct _struct_hash_table
{
    unsigned int uiNode;
    unsigned int uiBucketNum;
    unsigned int uiNodeCount;
    unsigned int uiAgingBucket;
    struct_bucket *pstHashTable;
    struct_hash_node *pstFreeHead;
    struct_hash_node *pstFreeTail;
} struct_hash_table;

#define clock_xxx_is_timeout(current_clock, timeout_clock) (current_clock > timeout_clock)
#define SYS_PARAM_BUCKET_NUM 0X10

struct_hash_table *g_pst_table = NULL;
static unsigned int get_hash_value(struct_hash_table *pstTable, const struct_hash_key *pstKey)
{
    unsigned int uiHash;
    uiHash = (pstKey->uiIp + pstKey->uiTeid) % pstTable->uiBucketNum;
    return uiHash;
}

static unsigned int compare(const struct_hash_key *pstKey, const struct_hash_key *pstKeyHash)
{
    if (pstKey->uiIp == pstKeyHash->uiIp && pstKey->uiTeid == pstKeyHash->uiTeid)
    {
        return 1;
    }
    return 0;
}

struct_hash_table *create_hash_table(unsigned int uiBucketNum, unsigned int uiNodeNum)
{
    unsigned long long u64_mem_count;
    int i;
    struct_hash_table *pstTable;
    if (0 == uiBucketNum || 0 == uiNodeNum)
    {
        printf("0 bucketNum or node num error!!\n");
    }

    u64_mem_count = sizeof(struct_hash_table) + 
        sizeof(struct_bucket) * uiBucketNum +
        sizeof(struct_hash_node) * uiNodeNum;

    pstTable = (struct_hash_table *)malloc(u64_mem_count);
    pstTable->pstHashTable = (struct_bucket *)(void *)&pstTable[1];
    pstTable->pstFreeHead = (struct_hash_node *)&pstTable->pstHashTable[uiBucketNum];
    memset(pstTable->pstFreeHead, 0, sizeof(struct_hash_node) * uiNodeNum);
    for (i = 0; i < uiNodeNum -1; i++)
    {
        pstTable->pstFreeHead[i].pstNext = &pstTable->pstFreeHead[i + 1];
    }

    pstTable->pstFreeTail = &pstTable->pstFreeHead[uiNodeNum -1];
    pstTable->pstFreeTail->pstNext = NULL;
    pstTable->uiBucketNum = uiBucketNum;
    pstTable->uiNodeCount = uiNodeNum;
    pstTable->uiAgingBucket = 0;

    return pstTable;
}

struct_hash_node *add_hash_key(struct_hash_table *pstTable, const struct_hash_key *pstKey)
{
    unsigned int uiHashIndex;
    struct_hash_node *pstNode;
    pstNode = pstTable->pstFreeHead;
    if (NULL == pstNode)
    {
        return NULL;
    }
    pstTable->pstFreeHead = pstTable->pstFreeHead->pstNext;
    if (NULL == pstTable->pstFreeHead)
    {
        pstTable->pstFreeTail = NULL;
    }

    pstNode->stKey.uiIp = pstKey->uiIp;
    pstNode->stKey.uiTeid = pstKey->uiTeid;

    uiHashIndex = get_hash_value(pstTable, pstKey);
    pstNode->pstNext = pstTable->pstHashTable[uiHashIndex].pstHead;
    pstNode->u64_timeout = 0;
    pstTable->pstHashTable[uiHashIndex].pstHead = pstNode;
    pstTable->pstHashTable[uiHashIndex].uiBucketLen++;
    pstTable->uiNodeCount++;

    return pstNode;
}

struct_hash_node * find_hash_node(struct_hash_table *pstTable, const struct_hash_key *pstKey)
{
    unsigned int uiHashIndex;
    struct_hash_node *pstNode = NULL;
    uiHashIndex = get_hash_value(pstTable, pstKey);
    pstNode = pstTable->pstHashTable[uiHashIndex].pstHead;
    while (NULL != pstNode)
    {
        if (compare(pstKey, &pstNode->stKey))
        {
            break;
        }
        pstNode = pstNode->pstNext;
    }

    return pstNode;
}


void delete_hash_node(struct_hash_table *pstTable, struct_hash_node *pstNode)
{
    unsigned uiHashIndex;
    struct_hash_node *pstNodeCur = NULL;
    struct_hash_node *pstNodePre = NULL;
    uiHashIndex = get_hash_value(pstTable, &pstNode->stKey);
    pstNodeCur = pstTable->pstHashTable[uiHashIndex].pstHead;
    if (NULL == pstNodeCur)
    {
        return;
    }
    if (pstNodeCur == pstNode)
    {
        pstTable->pstHashTable[uiHashIndex].pstHead = pstNode->pstNext;
    }
    else
    {
        pstNodePre = pstTable->pstHashTable[uiHashIndex].pstHead;
        pstNodeCur = pstNodePre->pstNext;

        while (NULL != pstNodeCur)
        {
            if (pstNodeCur == pstNode)
            {
                pstNodePre->pstNext = pstNode->pstNext;
                break;
            }
            pstNodePre = pstNodeCur;
            pstNodeCur = pstNodeCur->pstNext;
        }
    }
    memset(pstNode, 0, sizeof(struct_hash_node));
    if ((NULL == pstTable->pstFreeTail && NULL == pstTable->pstFreeHead))
    {
        pstTable->pstFreeHead = pstNode;
        pstTable->pstFreeTail = pstNode;
    }
    else
    {
        pstTable->pstFreeTail->pstNext = pstNode;
        pstTable->pstFreeTail = pstNode;
    }

    return;
}

void aging(struct_hash_table *pstTable, unsigned int u32_max_buckets,
        unsigned long long u64_timeout)
{
    if (NULL == pstTable)
    {
        return;
    }
    if (0 == pstTable->uiNodeCount)
    {
        return;
    }

    unsigned int uiHashIndex;
    unsigned int u32_loop_for_bucket_count = 0;
    for (uiHashIndex = pstTable->uiAgingBucket; uiHashIndex < SYS_PARAM_BUCKET_NUM; uiHashIndex++)
    {
        struct_hash_node *pstNodeCur = pstTable->pstHashTable[uiHashIndex].pstHead;
        struct_hash_node *pstNodePre = pstTable->pstHashTable[uiHashIndex].pstHead;

        while (NULL != pstNodeCur)
        {
            if (clock_xxx_is_timeout(u64_timeout, pstNodeCur->u64_timeout))
            {
                struct_hash_node *pstNodeNext = pstNodeCur->pstNext;
                if (pstNodeCur == pstTable->pstHashTable[uiHashIndex].pstHead)
                {
                    pstTable->pstHashTable[uiHashIndex].pstHead = pstNodeCur->pstNext;
                }
                else
                {
                    pstNodePre->pstNext = pstNodeCur->pstNext;
                }

                memset(pstNodeCur, 0, sizeof(struct_hash_node));
                if (NULL == pstTable->pstFreeHead && NULL == pstTable->pstFreeHead)
                {
                    pstTable->pstFreeHead = pstNodeCur;
                    pstTable->pstFreeTail = pstNodeCur;
                }
                else
                {
                    pstTable->pstFreeTail->pstNext = pstNodeCur;
                    pstTable->pstFreeTail = pstNodeCur;
                }
                pstNodeCur = pstNodeNext;
            }
            else
            {
                pstNodePre = pstNodeCur;
                pstNodeCur = pstNodeCur->pstNext;
            }
        }
        u32_loop_for_bucket_count++;
        pstTable->uiAgingBucket++;
        if (pstTable->uiAgingBucket >= pstTable->uiBucketNum)
        {
            pstTable->uiAgingBucket = 0;
        }

        if (u32_loop_for_bucket_count >= u32_max_buckets)
        {
            break;
        }
    }
    return;
}

int main(void)
{
    unsigned int uiBucketNum = 10;
    unsigned int uiNodeNum = 100;
    struct_hash_node *pstNode = NULL;
    struct_hash_key  stKey;
    stKey.uiIp = 0xffffffff;
    stKey.uiTeid = 0x12345678;
    g_pst_table = create_hash_table(uiBucketNum, uiNodeNum);

    add_hash_key(g_pst_table, &stKey);
    pstNode = find_hash_node(g_pst_table, &stKey);
    if (NULL == pstNode)
    {
        printf("The node has been found\n");
    }

    delete_hash_node(g_pst_table, pstNode);
    pstNode = find_hash_node(g_pst_table, &stKey);
    if (NULL == pstNode)
    {
        printf("The node hash been deleted!!\n");
    }

    add_hash_key(g_pst_table, &stKey);
    aging(g_pst_table, 10, 0xffffffff);
    pstNode = find_hash_node(g_pst_table, &stKey);
    if (NULL == pstNode)
    {
        printf("Aging successfully!!\n");
    }

    free(g_pst_table);

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值