1. 程式人生 > >雜湊表--開散列表

雜湊表--開散列表

下面為開散列表的程式碼實現:

HashBucket.h

#ifndef __HASHBUCKET_H__
#define __HASHBUCKET_H__


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



typedef int DataType;

typedef size_t(*PDTInt)(DataType str);


//雜湊桶的每個節點型別
typedef struct HashBucketNode
{
    DataType _data;
    struct
HashBucketNode* _pNext; }HBN; //雜湊桶型別 typedef struct HushBucket { HBN** _table; //雜湊桶空間--放的是節點的地址,所以是二級指標 int _capacity; //空間容量 int _size; //共有多少個有效元素--總節點個數 PDTInt pDTInt; //將資料型別轉化為整形,因為雜湊函式除留餘數法 }HBucket; //初始化 void HashBucketInit(HBucket* ht, int capacity, PDTInt pDTInt); //建立雜湊桶節點
HBN* BuyHushBucketNode(DataType data); //插入元素 -- data唯一 void HashBucketInsertUnique(HBucket* ht, DataType data); //刪除元素--data唯一 void HashBucketDeleteUnique(HBucket* ht, DataType data); //插入元素--data不唯一 void HashBucketInsertEqual(HBucket* ht, DataType data); //刪除所有值為data的節點 void HashBucketDeleteEqual(HBucket* ht, DataType data); //雜湊桶中共有多少個節點
int HashBucketSize(HBucket* ht); //判空 int HashBucketEmpty(HBucket* ht); //雜湊桶中共有多少個桶 int HashBucketCount(HBucket* ht); //在桶號為BucketNO的桶中有多少個節點 int HashBucketBucketSize(HBucket* ht, int BucketNo); //列印雜湊桶 void PrintHashBucket(HBucket* ht); //銷燬雜湊桶 void HashBucketDestroy(HBucket* ht); #endif

HashBucket.c

#include "HashBucket.h"
#include "comm.h"


//雜湊函式
static int HashFunc(HBucket* ht, int data)
{
    assert(ht);

    return ht->pDTInt(data) % (ht->_capacity);
}


//初始化
void HashBucketInit(HBucket* ht, int capacity, PDTInt pDTInt)
{
    assert(ht);

    capacity = GetCapacity(capacity);
    //calloc有初始化,將每個指標初始化為NULL
    ht->_table = (HBN**)calloc(capacity, sizeof(HBN*));

    if (NULL == ht->_table)
    {
        assert(0);
        return;
    }

    ht->_size = 0;
    ht->_capacity = capacity;
    ht->pDTInt = pDTInt;
}

//建立雜湊桶節點
HBN* BuyHushBucketNode(DataType data)
{
    HBN* pNewNode = NULL;
    pNewNode = (HBN*)malloc(sizeof(HBN));
    if (pNewNode == NULL)
    {
        assert(0);
        return NULL;
    }

    pNewNode->_data = data;
    pNewNode->_pNext = NULL;
    return pNewNode;
}

//插入元素 -- data唯一
void HashBucketInsertUnique(HBucket* ht, DataType data)
{
    int BucketNo = -1;  
    HBN* pCur = NULL;
    assert(ht);

    BucketNo = HashFunc(ht, data);//用雜湊函式算出插入資料的桶號

    //先判斷桶號所指的連結串列中是否已經存在data
    pCur = ht->_table[BucketNo];
    while (pCur)
    {
        //如果已經存在就返回
        if (pCur->_data == data)
            return;

        pCur = pCur->_pNext;
    }

    //不存在直接頭插
    pCur = BuyHushBucketNode(data); //建立新節點
    pCur->_pNext = ht->_table[BucketNo];
    ht->_table[BucketNo] = pCur;
    ht->_size++;
}

//刪除元素--data唯一
void HashBucketDeleteUnique(HBucket* ht, DataType data)
{
    int BucketNo = -1;
    HBN* pCur = NULL;
    HBN* pPre = NULL;
    assert(ht);

    BucketNo = HashFunc(ht, data);//用雜湊函式算出插入資料的桶號

    //找到data
    pCur = ht->_table[BucketNo];
    while (pCur)
    {

        if (pCur->_data == data)
        {
            //為第一個個節點
            if (pCur == ht->_table[BucketNo])
                ht->_table[BucketNo] = pCur->_pNext;

            else
                pPre->_pNext = pCur->_pNext;

            free(pCur);
            ht->_size--;
            return;
        }


        else
        {
            pPre = pCur;
            pCur = pCur->_pNext;
        }

    }


}

//插入元素--data不唯一
void HashBucketInsertEqual(HBucket* ht, DataType data)
{
    int BucketNo = -1;
    HBN* pCur = NULL;

    assert(ht);
    BucketNo = HashFunc(ht, data);

    //直接頭插
    pCur = BuyHushBucketNode(data);
    pCur->_pNext = ht->_table[BucketNo];
    ht->_table[BucketNo] = pCur;
    ht->_size++;
}

//刪除所有值為data的節點
void HashBucketDeleteEqual(HBucket* ht, DataType data)
{
    int BucketNo = -1;
    HBN* pCur = NULL;
    HBN* pPre = NULL;

    assert(ht);
    BucketNo = HashFunc(ht, data);
    pCur = ht->_table[BucketNo];
    while (pCur)
    {
        if (pCur->_data == data)
        {
            //第一個節點
            if (pCur == ht->_table[BucketNo])
            {
                ht->_table[BucketNo] = pCur->_pNext;
                free(pCur);

                //從頭開始繼續找
                pCur = ht->_table[BucketNo];
            }

            else
            {
                pPre->_pNext = pCur->_pNext;
                free(pCur);

                //從下個節點繼續找
                pCur = pPre->_pNext;
            }

            ht->_size--;

        }

        else
        {
            pPre = pCur;
            pCur = pCur->_pNext;
        }
    }
}

//雜湊桶中共有多少個節點
int HashBucketSize(HBucket* ht)
{
    assert(ht);
    return ht->_size;
}

//判空
int HashBucketEmpty(HBucket* ht)
{
    assert(ht);
    return 0 == ht->_size;
}

//雜湊桶中共有多少個桶
int HashBucketCount(HBucket* ht)
{
    assert(ht);
    return ht->_capacity;
}

//在桶號為BucketNO的桶中有多少個節點
int HashBucketBucketSize(HBucket* ht, int BucketNo)
{
    int count = 0;
    HBN* pCur = NULL;
    assert(ht);

    pCur = ht->_table[BucketNo];
    while (pCur)
    {
        count++;
        pCur = pCur->_pNext;
    }

    return count;
}

//銷燬雜湊桶
void HashBucketDestroy(HBucket* ht)
{
    int i = 0;
    HBN* pCur;
    assert(ht);

    for (; i < ht->_capacity; i++)
    {
        pCur = ht->_table[i];

        while (pCur)
        {
            ht->_table[i] = pCur->_pNext;
            free(pCur);
            pCur = ht->_table[i];
        }
    }

    ht->_capacity = 0;
    ht->_size = 0;
    free(ht->_table);
    ht->_table = NULL;
}

//列印雜湊桶
void PrintHashBucket(HBucket* ht)
{
    assert(ht);
    int i = 0;

    for (; i < ht->_capacity; i++)
    {
        HBN* pCur = ht->_table[i];
        printf("HashTable[%d]:", i);
        while (pCur)
        {
            printf("%d-->", pCur->_data);
            pCur = pCur->_pNext;
        }

        printf("\n");
    }
}

test.c

include “comm.h”

include “HashBucket.h”

void TestHashBucket()
{
    HBucket ht;

    HashBucketInit(&ht, 10, IntToInt);

    HashBucketInsertUnique(&ht, 2);//插入元素,data唯一
    HashBucketInsertUnique(&ht, 4);
    HashBucketInsertUnique(&ht, 6);
    HashBucketInsertUnique(&ht, 12);
    HashBucketDeleteUnique(&ht, 6);//刪除data
    printf("HashBucketSize:%d\n", HashBucketSize(&ht));
    printf("HashBucketCount:%d\n", HashBucketCount(&ht));
    printf("HashBucketBucketSize:%d\n", HashBucketBucketSize(&ht, 2));


    HashBucketInsertEqual(&ht, 2);//插入元素,data不唯一
    printf("HashBucketSize:%d\n", HashBucketSize(&ht));
    printf("HashBucketCount:%d\n", HashBucketCount(&ht));
    printf("HashBucketBucketSize:%d\n", HashBucketBucketSize(&ht, 2));
    HashBucketDeleteEqual(&ht, 2);//刪除所有值為data的元素
    printf("HashBucketBucketSize:%d\n", HashBucketBucketSize(&ht, 2));

    HashBucketDestroy(&ht);
}

int main()
{
    //TestHashTable();//動態閉雜湊雜湊表
    TestHashBucket();//開雜湊雜湊桶
}