雜湊表--開散列表
阿新 • • 發佈:2019-02-03
下面為開散列表的程式碼實現:
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();//開雜湊雜湊桶
}