# 搜索结构之哈希-----开散列

###### 搜索结构之哈希-----开散列

Hash(37)=4
Hash(25)=3
Hash(14)=3
Hash(36)=3
Hash(49)=5
Hash(68)=2
Hash(57)=2
Hash(11)=0

Hash_Bucket.h

typedef int DataType;
typedef struct Hash_Node{
struct Hash_Node* _pNext;
DataType _data;
}Hash_Node,*pHash_Node;
typedef int (*pElemToInt)(DataType data);
typedef struct Hash_Bucket{
pHash_Node* _HashTable;
int _size;
int _capacity;
pElemToInt _pElemToInt;
}Hash_Bucket;
int ElemToint(int data);
int Strtoint(const char * str);
//初始化
void  HashBucketInit(Hash_Bucket *hb, pElemToInt ElemToInt);

//扩容

//插入（元素不重复）
void  HashBucketInsertUnique(Hash_Bucket*hb, DataType data);

//插入（元素可以重复）
void  HashBucketInsertEqual(Hash_Bucket*hb, DataType data);

//删除
void  HashBucketDeleteUnique(Hash_Bucket*hb, DataType data);

//删除所有指定元素
void  HashBucketDeleteEquel(Hash_Bucket*hb, DataType data);

//找到指定元素
Hash_Node*  HashBucketFind(Hash_Bucket*hb, DataType data);

//桶的大小
int  HashBucketSize(Hash_Bucket*hb);

//桶是否为空
int HashBucketEmpty(Hash_Bucket*hb);

//销毁哈希桶
void HashBucketDestory(Hash_Bucket*hb);

//打印哈希桶
void HashBucketPrint(Hash_Bucket*hb);


Hash_Bucket.c

#include "HashBucket.h"
#include<malloc.h>
#include<stdlib.h>
#include<stdio.h>
#include<assert.h>
int HashFun(Hash_Bucket *hb,DataType data){
assert(hb);
return  (hb->_pElemToInt)(data) % (hb->_capacity);
}
//哈希字符串转换函数
int Strtoint(const char * str)
{
unsigned int seed = 131; // 31 131 1313 13131 131313
unsigned int hash = 0;
while (*str)
{
hash = hash * seed + (*str++);
}
return (hash & 0x7FFFFFFF);
}
//默认处理方式
int ElemToint(int data){
return data;
}
//素数表
int i = 0;
const int _PrimeSize = 28;
static const unsigned long _PrimeList[28] =
{
53ul, 97ul, 193ul, 389ul, 769ul,
1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
1610612741ul, 3221225473ul, 4294967291ul
};
for (i = 0; i < _PrimeSize; i++)
{
if (_PrimeList[i]>Old_Capacity)
return _PrimeList[i];
}
return -1;
}
//扩容
pHash_Node pcur = NULL;
int i = 0;
assert(hb);
pHash_Node * _newTable = (pHash_Node *)malloc(sizeof(pHash_Node)*new_capacity);
if (_newTable==NULL)
{
assert(0);
return;
}
for ( i = 0; i < new_capacity; i++)
{
_newTable[i]->_pNext = NULL;
}
for (i=0; i < hb->_capacity;i++){
pcur = hb->_HashTable[i];
int  new_bucketNober = -1;
while (pcur)
{
hb->_HashTable[i] = pcur->_pNext;
//插入pcur节点到_newTable中
new_bucketNober = hb->_pElemToInt(pcur->_data) % new_capacity;
pcur->_pNext = _newTable[new_bucketNober];
_newTable[new_bucketNober] = pcur;
pcur = hb->_HashTable[i];
}
}
free(hb->_HashTable);
hb->_HashTable = _newTable;
hb->_capacity = new_capacity;
}

//初始化
void  HashBucketInit(Hash_Bucket *hb, pElemToInt  ElemToInt){
int i = 0;
assert(hb);
hb->_capacity = 3;
hb->_HashTable = (pHash_Node *)malloc(sizeof(pHash_Node)*(hb->_capacity));
if (hb->_HashTable==NULL)
{
assert(0);
return;
}
for ( i = 0; i < hb->_capacity; i++)
{
hb->_HashTable[i] = NULL;
}
hb->_size = 0;
hb->_pElemToInt = ElemToInt;
}
Hash_Node *ret = (Hash_Node *)malloc(sizeof(Hash_Node));
if (ret==NULL)
{
assert(0);
return;
}
ret->_data = data;
ret->_pNext = NULL;
return ret;
}
//插入（元素不重复）
void  HashBucketInsertUnique(Hash_Bucket*hb, DataType data){
Hash_Node*pcur = NULL;
Hash_Node*NewNode = NULL;
assert(hb);
if (hb->_capacity==hb->_size)
{
}
while (pcur)
{
if (pcur->_data==data)
return;
else
pcur = pcur->_pNext;
}
}
//插入（元素可以重复）
void  HashBucketInsertEqual(Hash_Bucket*hb, DataType data){
Hash_Node*NewNode = NULL;
assert(hb);
}

//删除（元素不重复）
void  HashBucketDeleteUnique(Hash_Bucket*hb, DataType data){
Hash_Node*pcur = NULL;
Hash_Node*pre = NULL;
assert(hb);
while (pcur)
{
if (pcur->_data == data)
{
else
pre->_pNext = pcur->_pNext;
free(pcur);
hb->_size--;
return;
}
else
{
pre = pcur;
pcur = pcur->_pNext;
}
}

}

//删除（元素有可能重复）
void  HashBucketDeleteEquel(Hash_Bucket*hb, DataType data){

Hash_Node*pcur = NULL;
Hash_Node*pre = NULL;
assert(hb);
while (pcur)
{
if (pcur->_data == data)
{
{
free(pcur);
}
else
{
pre->_pNext = pcur->_pNext;
free(pcur);
pcur = pre->_pNext;
}

hb->_size--;

}
else
{
pre = pcur;
pcur = pcur->_pNext;
}

}
}

//找到指定元素
Hash_Node*  HashBucketFind(Hash_Bucket*hb, DataType data){
Hash_Node*pcur = NULL;
assert(hb);
while (pcur)
{
if (pcur->_data == data)
return pcur;
else
pcur = pcur->_pNext;
}
return NULL;
}

//桶的大小
int  HashBucketSize(Hash_Bucket*hb){
return hb->_size;
}

//桶是否为空
int HashBucketEmpty(Hash_Bucket*hb){
return 0 == hb->_size;
}

//销毁哈希桶
void HashBucketDestory(Hash_Bucket*hb){
int i = 0;
assert(hb);
for ( i = 0; i < hb->_capacity; i++)
{
free(hb->_HashTable[i]);
}
free(hb->_HashTable);
hb->_capacity = 0;
hb->_size = 0;
}
//打印哈希桶
void HashBucketPrint(Hash_Bucket*hb){
Hash_Node *pcur = NULL;
int i = 0;
assert(hb);
for (i = 0; i < hb->_capacity; i++)
{
pcur = hb->_HashTable[i];
while (pcur)
{
printf("%d---", pcur->_data);
pcur = pcur->_pNext;
}
printf("\n");
}
}



test.c

#include "HashBucket.h"
#include<stdio.h>
#include<stdlib.h>
int main(){
Hash_Node* ret;
Hash_Bucket hb;
HashBucketInit(&hb, ElemToint);
HashBucketInsertUnique(&hb,37);
HashBucketInsertUnique(&hb,25);
HashBucketInsertUnique(&hb,14);
HashBucketInsertUnique(&hb,36);
HashBucketInsertUnique(&hb,49);
HashBucketInsertUnique(&hb,68);
HashBucketInsertUnique(&hb,57);
HashBucketInsertUnique(&hb,11);
HashBucketInsertEqual(&hb, 14);
HashBucketInsertEqual(&hb, 68);
//HashBucketPrint(&hb);
//HashBucketDeleteEquel(&hb, 14);
printf("//////////");
HashBucketPrint(&hb);
ret = HashBucketFind(&hb, 11);
printf("%d\n",ret->_data);
HashBucketDeleteUnique(&hb, 49);
HashBucketPrint(&hb);
system("pause");
return 0;
}

开散列最坏的情况是:所有的元素都同一个哈希地址中的链表上,如此下去,随着容量越来越大,就会导致链表的长度很长,而链表的查找时间复杂度为o(N),就会失去哈希原本的效率,所以我们可以将链表改为红黑树,时间复杂度为lg(N).